@@ -27,9 +27,106 @@ All rights reserved. | |||
<li>1.8.7 available 9-Sep-2015 | |||
</ul> | |||
<!-- | |||
<h2>Notable changes</h2> | |||
--> | |||
<h3>ajdoc</h3> | |||
<p>The ajdoc tool has been fixed! It is now working again if run on a 1.7 JDK.</p> | |||
<h3>Dynamic weaver attachment</h3> | |||
<p>The AspectJ loadtime weaving agent can now be dynamically attached to a JVM after it has started | |||
(you don't need to use -javaagent). This offers extra flexibility but obviously any | |||
classes loaded before attachment will not be woven.</p> | |||
<p>Here is a simple aspect:</p> | |||
<code><pre> | |||
public aspect Azpect { | |||
before(): execution(* *(..)) { | |||
System.out.println(thisJoinPointStaticPart); | |||
} | |||
} | |||
</pre></code> | |||
<p>Compiled via:</p> | |||
<code><pre>ajc -1.8 Azpect.java -outxml</pre></code> | |||
<p>This produces a compiled class <tt>Azpect.class</tt> and a file <tt>META-INF/aop-ajc.xml</tt>.</p> | |||
<p>I then have this sample application (same directory):</p> | |||
<code><pre> | |||
import java.lang.management.ManagementFactory; | |||
import org.aspectj.weaver.loadtime.Agent; | |||
import com.sun.tools.attach.VirtualMachine; | |||
public class Application { | |||
public static void main(String[] args) { | |||
if (!isAspectJAgentLoaded()) | |||
System.err.println("WARNING: AspectJ weaving agent not loaded"); | |||
new Sample().doSomething(); | |||
} | |||
public static boolean isAspectJAgentLoaded() { | |||
try { | |||
Agent.getInstrumentation(); | |||
} catch (NoClassDefFoundError e) { | |||
System.out.println(e); | |||
return false; | |||
} catch (UnsupportedOperationException e) { | |||
System.out.println(e); | |||
return dynamicallyLoadAspectJAgent(); | |||
} | |||
return true; | |||
} | |||
public static boolean dynamicallyLoadAspectJAgent() { | |||
String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); | |||
int p = nameOfRunningVM.indexOf('@'); | |||
String pid = nameOfRunningVM.substring(0, p); | |||
try { | |||
VirtualMachine vm = VirtualMachine.attach(pid); | |||
String jarFilePath = System.getProperty("AGENT_PATH"); | |||
vm.loadAgent(jarFilePath); | |||
vm.detach(); | |||
} catch (Exception e) { | |||
System.out.println(e); | |||
return false; | |||
} | |||
return true; | |||
} | |||
} | |||
</pre></code> | |||
<p>And this Sample class:</p> | |||
<code><pre> | |||
public class Sample { | |||
public void doSomething() { | |||
System.out.println("Do something"); | |||
System.out.println("Square of 7 = " + square(7)); | |||
} | |||
private int square(int i) { | |||
return i * i; | |||
} | |||
} | |||
</pre></code> | |||
<p>Compile these with javac, <b>but you must have the aspectjweaver and the JDK tools.jar on your classpath</b>.</p> | |||
<p>Once compiled we can run it:</p> | |||
<code><pre>java -DAGENT_PATH=<path-to>/aspectjweaver.jar Application</pre></code> | |||
<p>What does it do? The main method calls the function that detects whether the agent is attached, if it is not then | |||
it programmatically attaches it using the <tt>VirtualMachine</tt> class. Then the main method accesses the | |||
Sample class. At this point in program execution the Sample class is loaded and because the agent has been | |||
attached it gets woven. Notice that the <tt>Application</tt> class itself is not woven because it was loaded prior | |||
to agent attachment.</p> | |||
<p>Thanks to Alexander Kriegisch for the sample code and the patch to add this behaviour to AspectJ.</p> | |||
<!-- ============================== --> | |||
</body> |
@@ -0,0 +1,22 @@ | |||
//import com.flickbay.orientdb.OrientKey; | |||
class OrientKey<T> { | |||
} | |||
class SimpleOrientDBValue extends OrientDBValue {} | |||
class OrientDBValue<T> {} | |||
public aspect OrientDBKeyIO { | |||
public interface IO<T> { | |||
OrientDBValue<T> getOrientDBValue(); | |||
} | |||
declare parents : OrientKey implements IO; | |||
public SimpleOrientDBValue OrientKey<T>.value = null; | |||
public OrientDBValue OrientKey<T>.getOrientDBValue() { return this.value; } | |||
} | |||
@@ -0,0 +1,42 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2014 Contributors | |||
* All rights reserved. This program and the accompanying materials | |||
* are made available under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution, and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.systemtest.ajc188; | |||
import java.io.File; | |||
import java.lang.reflect.Method; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import junit.framework.Test; | |||
import org.aspectj.testing.XMLBasedAjcTestCase; | |||
/** | |||
* @author Andy Clement | |||
*/ | |||
public class Ajc188Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | |||
public void testCompileError_478003() throws Exception { | |||
runTest("compile error"); | |||
} | |||
// --- | |||
public static Test suite() { | |||
return XMLBasedAjcTestCase.loadSuite(Ajc188Tests.class); | |||
} | |||
@Override | |||
protected File getSpecFile() { | |||
return getClassResource("ajc188.xml"); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2014 Contributors | |||
* All rights reserved. This program and the accompanying materials | |||
* are made available under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution, and is available at | |||
* http://www.eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.systemtest.ajc188; | |||
import junit.framework.Test; | |||
import junit.framework.TestSuite; | |||
import org.aspectj.systemtest.apt.AptTests; | |||
public class AllTestsAspectJ188 { | |||
public static Test suite() { | |||
TestSuite suite = new TestSuite("AspectJ 1.8.8 tests"); | |||
// $JUnit-BEGIN$ | |||
suite.addTest(Ajc188Tests.suite()); | |||
// $JUnit-END$ | |||
return suite; | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]> | |||
<suite> | |||
<ajc-test dir="bugs188/478003" title="compile error"> | |||
<compile files="OrientDBKeyIO.java" options="-1.8"/> | |||
</ajc-test> | |||
</suite> |
@@ -375,7 +375,12 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
// for that type | |||
if (m.isTargetTypeParameterized()) { | |||
ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType(); | |||
m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType)); | |||
ResolvedType actualOccurrence = newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType); | |||
if (actualOccurrence == null) { | |||
// Handle the case where the ITD is onto the type targeted by the declare parents (PR478003) | |||
actualOccurrence = newParentTarget.getType().discoverActualOccurrenceOfTypeInHierarchy(genericOnType); | |||
} | |||
m = m.parameterizedFor(actualOccurrence); | |||
// possible sig change when type parameters filled in | |||
sig = m.getSignature(); | |||
} |