]> source.dussan.org Git - aspectj.git/commitdiff
Workaround for defining classes during LTW
authorAlexander Kriegisch <Alexander@Kriegisch.name>
Sun, 28 Jan 2024 09:13:22 +0000 (16:13 +0700)
committerAlexander Kriegisch <Alexander@Kriegisch.name>
Mon, 29 Jan 2024 00:07:26 +0000 (07:07 +0700)
Overhaul ClassLoaderWeavingAdaptor to use statically initialised Unsafe
instances and method handles pointing to their 'defineClass' methods.
Those now work universally on JDKs 8-21. In older JDKs, the method used
to be in sun.misc.Unsafe, in more recent ones on jdk.internal.misc.Unsafe.
It is challenging to fetch instances, especially as reflection
protection and module boundaries have been increased in the JDK
progressively. But finally, a solution was adapted from Byte Buddy (BB).
Kudos to BB author Rafael Winterhalter. The previous solution to use
ClassLoader::defineClass and require '--add-opens' is no longer
necessary for the first time since it became necessary in AspectJ 1.9.7
with Java 16 support.

Add org.ow2.asm:asm-common as a dependency everywhere org.ow2.asm:asm
was used before. Maybe that is too many places, but no worse than before.

Add missing dependency on loadtime to aspectjweaver. This kept a build
like "mvn install -am -pl aspectjweaver" from picking up changed
loadtime classes.

Fixes #117.

Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
29 files changed:
ajde.core/pom.xml
ajde/pom.xml
ajdoc/pom.xml
aspectjtools/pom.xml
aspectjweaver/aspectjweaver-assembly.xml
aspectjweaver/pom.xml
loadtime/pom.xml
loadtime/src/main/java/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java
org.aspectj.ajdt.core/pom.xml
org.aspectj.ajdt.core/src/test/java/org/aspectj/tools/ajc/Ajc.java
org.aspectj.ajdt.core/src/test/java/org/aspectj/tools/ajc/AjcTestCase.java
pom.xml
run-all-junit-tests/pom.xml
taskdefs/pom.xml
testing-drivers/pom.xml
testing/pom.xml
testing/src/test/java/org/aspectj/testing/AntSpec.java
testing/src/test/java/org/aspectj/testing/RunSpec.java
tests/bugs153/pr155033/ant.xml
tests/bugs153/pr157474/ant-server.xml
tests/bugs153/pr158957/ant.xml
tests/java5/ataspectj/ajc-ant.xml
tests/java5/ataspectj/ataspectj/UnweavableTest.java
tests/ltw/ant-server.xml
tests/ltw/ant.xml
tests/pom.xml
tests/profiling/build.xml
tests/tracing/ant.xml
weaver/pom.xml

index 8b147cdcfd1baf3fbd0387e126c06d1480246390..4741247178a72882c837a86c5055db0e1a332fb3 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>testing-util</artifactId>
index dd552c5af398cc387eacc2fc3103504b944546ca..44428acc4b27330f035fdc6aac9ddbed4fe197cd 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>org.aspectj.ajdt.core</artifactId>
index cb22d214590b5debfea742d72896ac270743ecba..f183c37e9cd164194420eafe6bcf5ee0f880dc4f 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>testing-util</artifactId>
index 2280deb3f411fc93cd7d96c2d41a4f0bd2a450fa..12d18fecfee9ec8b9e2a11e3b8a44ca13a656b40 100644 (file)
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                </dependency>
+               <dependency>
+                       <groupId>org.ow2.asm</groupId>
+                       <artifactId>asm-commons</artifactId>
+               </dependency>
                <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>runtime</artifactId>
index 576bb2700996cb1a47aaa409014ac8b6138e4798..877ddf6b1ef67a070f1d5d5428d5402f89278d81 100644 (file)
@@ -17,6 +17,7 @@
                        <useProjectArtifact>false</useProjectArtifact>
                        <includes>
                                <include>org.ow2.asm:asm</include>
+                               <include>org.ow2.asm:asm-commons</include>
                        </includes>
                </dependencySet>
        </dependencySets>
index 34cefc74c9d64e8d58657f405f9df8c5f2c363d3..c5702e2aa567db77b807af05914323955f0a0e42 100644 (file)
                        <artifactId>weaver</artifactId>
                        <version>${project.version}</version>
                </dependency>
+               <dependency>
+                       <groupId>org.aspectj</groupId>
+                       <artifactId>loadtime</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
                <dependency>
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                </dependency>
+               <dependency>
+                       <groupId>org.ow2.asm</groupId>
+                       <artifactId>asm-commons</artifactId>
+               </dependency>
        </dependencies>
 
 </project>
index e73382812a026b9132417a39a9a724f55340d9f0..549ee286d9b96fa4c9f09edfc09e38f345e4bb4e 100644 (file)
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                </dependency>
+               <dependency>
+                       <groupId>org.ow2.asm</groupId>
+                       <artifactId>asm-commons</artifactId>
+               </dependency>
                <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>testing-util</artifactId>
index ad700fcfd0852b48734b716ca211119cd314a472..9a10520755560c57c0e00533a287b077dac72df9 100644 (file)
@@ -11,23 +11,16 @@ package org.aspectj.weaver.loadtime;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
 
 import org.aspectj.bridge.AbortException;
 import org.aspectj.bridge.Constants;
@@ -54,6 +47,9 @@ import org.aspectj.weaver.tools.TraceFactory;
 import org.aspectj.weaver.tools.WeavingAdaptor;
 import org.aspectj.weaver.tools.cache.WeavedClassCache;
 
+import org.objectweb.asm.*;
+import org.objectweb.asm.commons.ClassRemapper;
+import org.objectweb.asm.commons.Remapper;
 import sun.misc.Unsafe;
 
 /**
@@ -1029,156 +1025,243 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor {
                }
        }
 
-       private Unsafe unsafe;
+       private static final Object lock = new Object();
 
-       private Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
-               if (unsafe == null) {
-               Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
-               theUnsafeField.setAccessible(true);
-               return (Unsafe) theUnsafeField.get(null);
-               }
-               return unsafe;
-    }
+       /**
+        * Instance of either {@link sun.misc.Unsafe} or {@link jdk.internal.misc.Unsafe}. Luckily, both types have
+        * {@code defineClass} methods with identical signatures. I.e., method handle {@link #defineClassMethodHandle} can be
+        * invoked with the same set of parameters for both types.
+        */
+       private static Object unsafeInstance = null;
 
-       private static Method bindTo_Method, invokeWithArguments_Method = null;
-       private static Object defineClassMethodHandle = null;
+       /**
+        * Method handle for defining new classes in arbitrary class loaders. For invocation, use in connection with
+        * {@link #unsafeInstance}.
+        */
+       private static MethodHandle defineClassMethodHandle;
 
-       private static Boolean initializedForJava11 = false;
+       static {
+               try {
+                       createDefineClassMethodHandle();
+               }
+               catch (Exception initializationError) {
+                       new RuntimeException(
+                               "The aspect weaver cannot determine any valid method to define auxiliary classes in arbitrary class loaders. " +
+                                       "Aspect weaving will *not* work, and you will see subsequent errors. Please search for corresponding " +
+                                       "issues at https://github.com/eclipse-aspectj/aspectj/issues. If there are none, please create a new one.",
+                               initializationError
+                       ).printStackTrace();
+               }
+       }
 
-       // In order to let this code compile on earlier versions of Java (8), use reflection to discover the elements
-       // we need to define classes.
-       private static synchronized void initializeForJava11() {
-               if (initializedForJava11) return;
+       /**
+        * Scaffolding for defining classes in arbitrary class loaders
+        * <p>
+        * Inspired by and shamelessly adapted from <a href="https://bit.ly/3w10oH5">Byte Buddy's {@code ClassInjector}</a>.
+        * Special thanks to Byte Buddy (BB) author Rafael Winterhalter, who briefly mentioned this approach in a
+        * <a href="https://bit.ly/3SjFOZY">GitHub comment</a> related to JDK issue
+        * <a href="https://bugs.openjdk.org/browse/JDK-8200559">JDK-8200559</a>.
+        * <p>
+        * <b>Background:</b> Instead of BB, we use ASM and reflection as follows:
+        * <ul>
+        *   <li>
+        *     Create a mirror class for {@link AccessibleObject} with a different package name in a separate, throw-away
+        *     class loader.
+        *   </li>
+        *   <li>
+        *     Use the mirror class to calculate the {@link Unsafe#objectFieldOffset(Field)} for boolean field
+        *     {@link AccessibleObject#override}, which is expected to be identical to the offset of the same field in the
+        *     original class.
+        *   </li>
+        *   <li>
+        *     After we have the offset, we can use it to override the field value in the original class, deactivating access
+        *     checks for {@link jdk.internal.misc.Unsafe#defineClass(String, byte[], int, int, ClassLoader, ProtectionDomain)},
+        *     the method we need to execute using a method handle.
+        *   </li>
+        * </ul>
+        * All these serve the sole purpose enable LTW without {@code --add-opens java.base/java.lang=ALL-UNNAMED} on the
+        * JVM command line on JDK 16+, which was necessary for AspectJ 1.9.7 (Java 16) to 1.9.21 (Java 21).
+        *
+        * @throws Exception if anything goes wrong, trying to determine a usable {@code defineClass} method handle from any
+        * of the inspected classes
+        */
+       private static synchronized void createDefineClassMethodHandle() throws Exception {
+               Unsafe publicUnsafeInstance = null;
                try {
-                       // MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class, ProtectionDomain.class});
-                       Class<?> methodType_Class = Class.forName("java.lang.invoke.MethodType");
-                       Method methodTypeMethodOnMethodTypeClass = methodType_Class.getDeclaredMethod("methodType", Class.class,Class[].class);
-                       methodTypeMethodOnMethodTypeClass.setAccessible(true);
-                       Object defineClassMethodType = methodTypeMethodOnMethodTypeClass.invoke(null, Class.class, new Class[] {String.class,byte[].class,int.class,int.class,ProtectionDomain.class});
-
-                       // MethodHandles.Lookup methodHandlesLookup = MethodHandles.lookup();
-                       Class<?> methodHandles_Class = Class.forName("java.lang.invoke.MethodHandles");
-                       Method lookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("lookup");
-                       lookupMethodOnMethodHandlesClass.setAccessible(true);
-                       Object methodHandlesLookup = lookupMethodOnMethodHandlesClass.invoke(null);
-
-                       // MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, methodHandlesLookup);
-                       Class<?> methodHandlesLookup_Class = Class.forName("java.lang.invoke.MethodHandles$Lookup");
-                       Method privateLookupMethodOnMethodHandlesClass = methodHandles_Class.getDeclaredMethod("privateLookupIn",Class.class,methodHandlesLookup_Class);
-                       privateLookupMethodOnMethodHandlesClass.setAccessible(true);
-                       Object lookup = privateLookupMethodOnMethodHandlesClass.invoke(null, ClassLoader.class, methodHandlesLookup);
-
-                       // MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType);
-                       Method findVirtual_Method = methodHandlesLookup_Class.getDeclaredMethod("findVirtual", Class.class,String.class,methodType_Class);
-                       findVirtual_Method.setAccessible(true);
-                       defineClassMethodHandle = findVirtual_Method.invoke(lookup, ClassLoader.class, "defineClass",defineClassMethodType);
-
-                       // clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length);
-                       Class<?> methodHandle_Class = Class.forName("java.lang.invoke.MethodHandle");
-                       bindTo_Method = methodHandle_Class.getDeclaredMethod("bindTo", Object.class);
-                       invokeWithArguments_Method = methodHandle_Class.getDeclaredMethod("invokeWithArguments",Object[].class);
-
-                       initializedForJava11 = true;
-               } catch (Exception e) {
-                       e.printStackTrace();
+                       Field publicUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+                       publicUnsafeField.setAccessible(true);
+                       publicUnsafeInstance = (Unsafe) publicUnsafeField.get(null);
+                       synchronized (lock) {
+                               unsafeInstance = publicUnsafeInstance;
+                               defineClassMethodHandle =  createMethodHandle(
+                                       "sun.misc.Unsafe", "defineClass",
+                                       String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class
+                               );
+                       }
+               }
+               catch (Exception publicUnsafeException) {
+                       if (publicUnsafeInstance == null)
+                               throw publicUnsafeException;
+                       long overrideOffset = getAccessibleObjectOverrideOffset(publicUnsafeInstance);
+                       Class<?> internalUnsafeType = Class.forName("jdk.internal.misc.Unsafe");
+                       Field internalUnsafeField = internalUnsafeType.getDeclaredField("theUnsafe");
+                       publicUnsafeInstance.putBoolean(internalUnsafeField, overrideOffset, true);
+                       Method internalUnsafeDefineClassMethod = internalUnsafeType.getMethod(
+                               "defineClass",
+                               String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class
+                       );
+                       publicUnsafeInstance.putBoolean(internalUnsafeDefineClassMethod, overrideOffset, true);
+                       synchronized (lock) {
+                               unsafeInstance = internalUnsafeField.get(null);
+                               defineClassMethodHandle = createMethodHandle(internalUnsafeDefineClassMethod);
+                       }
                }
        }
 
-       private void defineClass(ClassLoader loader, String name, byte[] bytes, ProtectionDomain protectionDomain) {
-               if (trace.isTraceEnabled()) {
-                       trace.enter("defineClass", this, new Object[] { loader, name, bytes });
+       private static long getAccessibleObjectOverrideOffset(Unsafe unsafe)
+               throws IOException, ClassNotFoundException, NoSuchFieldException
+       {
+               Objects.requireNonNull(unsafe);
+               Field overrideField;
+               try {
+                       overrideField = AccessibleObject.class.getDeclaredField("override");
+               }
+               catch (NoSuchFieldException ignored) {
+                       // On JDK 12+, field AccessibleObject.override is protected from reflection. The work-around is to create a
+                       // mirror class with the same field layout by transforming the original class, so we can calculate the field
+                       // offset of 'override' and set a value in the original class using the now known offset.
+                       Class<?> mirrorClass = getMirrorClass(
+                               "java.lang.reflect.AccessibleObject", "org.aspectj.mirror.AccessibleObject", true
+                       );
+                       overrideField = mirrorClass.getDeclaredField("override");
+               }
+               return unsafe.objectFieldOffset(overrideField);
+       }
+
+       public static MethodHandle createMethodHandle(String className, String methodName, Class<?>... argumentTypes)
+               throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException
+       {
+               Class<?> clazz = Class.forName(className);
+               Method method = clazz.getDeclaredMethod(methodName, argumentTypes);
+               return createMethodHandle(method, false);
+       }
+
+       public static MethodHandle createMethodHandle(Method method) throws IllegalAccessException {
+               return createMethodHandle(method, false);
+       }
+
+       public static MethodHandle createMethodHandle(Method method, boolean setAccessible)
+               throws IllegalAccessException
+       {
+               // Use Method::setAccessible to access private methods. Caveat: This does not work for classes in packages not
+               // exported to the calling module (for LTW usually the unnamed module).
+               if (setAccessible)
+                       method.setAccessible(true);
+               return MethodHandles.lookup().unreflect(method);
+       }
+
+       @SuppressWarnings("SameParameterValue")
+       private static Class<?> getMirrorClass(String originalClass, String mirrorClass, boolean removeMethods)
+               throws IOException, ClassNotFoundException
+       {
+               Objects.requireNonNull(originalClass);
+               Objects.requireNonNull(mirrorClass);
+               if (mirrorClass.equals(originalClass))
+                       throw new IllegalArgumentException("Mirror class name must be different from original " + originalClass);
+               byte[] mirrorClassBytes = getMirrorClassBytes(originalClass, mirrorClass, removeMethods);
+               ClassLoader mirrorClassLoader = new SingleClassLoader(mirrorClass, mirrorClassBytes);
+               return mirrorClassLoader.loadClass(mirrorClass);
+       }
+
+       private static byte[] getMirrorClassBytes(String originalClass, String mirrorClass, boolean removeMethods)
+               throws IOException, ClassNotFoundException
+       {
+               Class<?> aClass = Class.forName(originalClass);
+               try (InputStream input = aClass.getResourceAsStream(aClass.getSimpleName() + ".class")) {
+                       Objects.requireNonNull(input);
+                       ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+                       ClassRemapper classRemapper = new ClassRemapper(classWriter, new ClassNameRemapper(originalClass, mirrorClass));
+                       ClassVisitor classVisitor = removeMethods ? new MethodAndConstructorRemover(classRemapper) : classRemapper;
+                       new ClassReader(input).accept(classVisitor, 0);
+                       return classWriter.toByteArray();
                }
-               Object clazz = null;
-               debug("generating class '" + name + "'");
-               if (LangUtil.is11VMOrGreater()) {
-                       try {
-                               if (!initializedForJava11) {
-                                       initializeForJava11();
-                               }
-                               // Do this: clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length, protectionDomain);
-                               Object o = bindTo_Method.invoke(defineClassMethodHandle,loader);
-                               clazz = invokeWithArguments_Method.invoke(o, new Object[] {new Object[] {name, bytes, 0, bytes.length, protectionDomain}});
+       }
 
-                       } catch (Throwable t) {
-                               t.printStackTrace(System.err);
-                               warn("define generated class failed", t);
-                       }
-               } else {
-                       try {
-                               if (defineClassMethod == null) {
-                                       synchronized (lock) {
-                                               getUnsafe();
-                                               defineClassMethod =
-                                                               Unsafe.class.getDeclaredMethod("defineClass", String.class,byte[].class,Integer.TYPE,Integer.TYPE, ClassLoader.class,ProtectionDomain.class);
-                                       }
-                               }
-                               defineClassMethod.setAccessible(true);
-                               clazz = defineClassMethod.invoke(getUnsafe(), name,bytes,0,bytes.length,loader,protectionDomain);
-                       } catch (LinkageError le) {
-                               le.printStackTrace();
-                               // likely thrown due to defining something that already exists?
-                               // Old comments from before moving to Unsafe.defineClass():
-                               // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
-                               // TODO maw I don't think this is OK and
-                       } catch (Exception e) {
-                               e.printStackTrace(System.err);
-                               warn("define generated class failed", e);
-                       }
+       private static class ClassNameRemapper extends Remapper {
+               private final String originalClass;
+               private final String mirrorClass;
+
+               public ClassNameRemapper(String originalClass, String mirrorClass) {
+                       this.originalClass = originalClass.replace('.', '/');
+                       this.mirrorClass = mirrorClass.replace('.', '/');
                }
 
-               if (trace.isTraceEnabled()) {
-                       trace.exit("defineClass", clazz);
+               @Override
+               public String map(String internalName) {
+                       return internalName.equals(originalClass) ? mirrorClass : internalName;
                }
        }
-       static Method defineClassMethod;
-       private static final Object lock = new Object();
 
+       /**
+        * ASM class visitor removing all methods and constructors from the given class, leaving only the original fields
+        */
+       private static class MethodAndConstructorRemover extends ClassVisitor {
+               public MethodAndConstructorRemover(ClassRemapper classRemapper) {
+                       super(Opcodes.ASM9, classRemapper);
+               }
 
-//    /*
-//    This method is equivalent to the following code but use reflection to compile on Java 7:
-//     MethodHandles.Lookup baseLookup = MethodHandles.lookup();
-//    MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup);
-//    MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType);
-//    handle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length));
-// */
-//@Override
-//@SuppressWarnings("unchecked")
-//public <T> Class<T> defineClass(ClassLoader classLoader, String className, byte[] classBytes) {
-//    Object baseLookup = methodHandlesLookup.invoke(null);
-//    Object lookup = methodHandlesPrivateLookupIn.invoke(null, ClassLoader.class, baseLookup);
-//    MethodHandle defineClassMethodHandle = (MethodHandle) lookupFindVirtual.invoke(lookup, ClassLoader.class, "defineClass", defineClassMethodType);
-//    try {
-//        return Cast.uncheckedCast(defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length));
-//    } catch (Throwable throwable) {
-//        throw new RuntimeException(throwable);
-//        return (Class) defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length);
-//    } catch (Throwable e) {
-//        throw new RuntimeException(e);
-//    }
-//}
-
-       private void defineClass(ClassLoader loader, String name, byte[] bytes){
-               defineClass(loader,name,bytes,null);//, ProtectionDomain protectionDomain) {
+               @Override
+               public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
+                       // Do not visit any methods or constructors, effectively removing them
+                       return null;
+               }
+       }
+
+       /**
+        * Throw-away child classloader with the sole purpose to define a single {@link Class} from the given bytecode
+        */
+       private static class SingleClassLoader extends ClassLoader {
+               private final String mirrorClass;
+               private final byte[] mirrorClassBytes;
+
+               private SingleClassLoader(String mirrorClass, byte[] mirrorClassBytes) {
+                       super(SingleClassLoader.class.getClassLoader());
+                       this.mirrorClass = mirrorClass;
+                       this.mirrorClassBytes = mirrorClassBytes;
+               }
+
+               @Override
+               public Class<?> loadClass(String name) throws ClassNotFoundException {
+                       return name.equals(mirrorClass)
+                               ? super.defineClass(null, mirrorClassBytes, 0, mirrorClassBytes.length)
+                               : super.loadClass(name);
+               }
+       }
+
+       private void defineClass(ClassLoader loader, String name, byte[] bytes) {
+               defineClass(loader, name, bytes, null);
+       }
+
+       private void defineClass(ClassLoader loader, String name, byte[] bytes, ProtectionDomain protectionDomain) {
+               if (trace.isTraceEnabled())
+                       trace.enter("defineClass", this, new Object[] { loader, name, bytes });
+               debug("generating class '" + name + "'");
+               Class<?> definedClass = null;
+               try {
+                       if (defineClassMethodHandle == null)
+                               throw new RuntimeException("no valid method to define auxiliary classes -> weaver not working");
+                       definedClass = (Class<?>) defineClassMethodHandle
+                               .bindTo(unsafeInstance)
+                               .invokeWithArguments(name, bytes, 0, bytes.length, loader, protectionDomain);
+               }
+               catch (Throwable t) {
+                       t.printStackTrace(System.err);
+                       warn("define generated class failed", t);
+               }
+               finally {
+                       if (trace.isTraceEnabled())
+                               trace.exit("defineClass", definedClass);
+               }
        }
-//             if (trace.isTraceEnabled()) {
-//                     trace.enter("defineClass", this, new Object[] { loader, name, bytes, protectionDomain });
-//             }
-//             Object clazz = null;
-//             debug("generating class '" + name + "'");
-//             try {
-//                     getUnsafe().defineClass(name, bytes, 0, bytes.length, loader, protectionDomain);
-//             } catch (LinkageError le) {
-//                     // likely thrown due to defining something that already exists?
-//                     // Old comments from before moving to Unsafe.defineClass():
-//                     // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
-//                     // TODO maw I don't think this is OK and
-//             } catch (Exception e) {
-//                     warn("define generated class failed", e);
-//             }
-//
-//             if (trace.isTraceEnabled()) {
-//                     trace.exit("defineClass", clazz);
-//             }
-//     }
 
 }
index 6ef954270c54d4b9d68a81cde78258756d31ff90..6bb09b6eb535f3f579033c881e9ae7fa955e1437 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
index 7f4ae01098c80c927e4163caac6ed6204497c694..c6d8c99a89531e289cb14270c726b97c618500f7 100644 (file)
@@ -38,8 +38,7 @@ import org.aspectj.util.FileUtil;
 
 import static java.io.File.pathSeparator;
 import static java.io.File.separator;
-import static org.aspectj.tools.ajc.AjcTestCase.CLASSPATH_ASM;
-import static org.aspectj.tools.ajc.AjcTestCase.CLASSPATH_JUNIT;
+import static org.aspectj.tools.ajc.AjcTestCase.*;
 
 /**
  * The Ajc class is intended for use as part of a unit-test suite, it drives the AspectJ compiler and lets you check the compilation
@@ -74,6 +73,7 @@ public class Ajc {
                        + outputFolder("bcel-builder")
                        + pathSeparator + CLASSPATH_JUNIT
                        + pathSeparator + CLASSPATH_ASM
+                       + pathSeparator + CLASSPATH_ASM_COMMONS
                        + outputFolder("bridge")
                        + outputFolder("loadtime")
                        + outputFolder("weaver")
index 9aec7d947df87839af27e3514c210af7cf16415b..6fb2d260269bdf8ab656feecbc619e5aa5ebcceb 100644 (file)
@@ -70,9 +70,15 @@ public abstract class AjcTestCase extends TestCase {
        public static final String CLASSPATH_ASM =
                Arrays.stream(System.getProperty("java.class.path")
                        .split(pathSeparator))
-                       .filter(path -> path.replace('\\', '/').contains("org/ow2/asm/"))
+                       .filter(path -> path.replace('\\', '/').contains("org/ow2/asm/asm/"))
                        .findFirst()
                        .orElseThrow(() -> new RuntimeException("ASM library not found on classpath"));
+       public static final String CLASSPATH_ASM_COMMONS =
+               Arrays.stream(System.getProperty("java.class.path")
+                       .split(pathSeparator))
+                       .filter(path -> path.replace('\\', '/').contains("org/ow2/asm/asm-commons/"))
+                       .findFirst()
+                       .orElseThrow(() -> new RuntimeException("ASM Commons library not found on classpath"));
        public static final String CLASSPATH_JDT_CORE =
                Arrays.stream(System.getProperty("java.class.path")
                        .split(pathSeparator))
@@ -102,6 +108,7 @@ public abstract class AjcTestCase extends TestCase {
                        + pathSeparator + ".." + separator + "lib" + separator + "bcel" + separator + "bcel-verifier.jar"
                        + pathSeparator + CLASSPATH_JDT_CORE
                        + pathSeparator + CLASSPATH_ASM
+                       + pathSeparator + CLASSPATH_ASM_COMMONS
                        // hmmm, this next one should perhaps point to an aj-build jar...
                        + pathSeparator + ".." + separator + "lib" + separator + "test" + separator + "aspectjrt.jar"
                ;
diff --git a/pom.xml b/pom.xml
index 823f65ccd8dd840200f7bb61a68b45dc6d70da0a..5a62b005e7d860adaa58a10b9bb782ec4666e412 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                                <artifactId>asm</artifactId>
                                <version>${asm.version}</version>
                        </dependency>
+                       <dependency>
+                               <groupId>org.ow2.asm</groupId>
+                               <artifactId>asm-commons</artifactId>
+                               <version>${asm.version}</version>
+                       </dependency>
                        <dependency>
                                <!-- All modules referencing files inside 'lib' need this dependency -->
                                <groupId>org.aspectj</groupId>
index 537d2db4134fe456a76a48ee1c6132333a0fd8f7..f2370f312914a49c2cbfe31acf1ccc06000758ea 100644 (file)
                        <artifactId>asm</artifactId>
                        <scope>test</scope>
                </dependency>
+               <dependency>
+                       <groupId>org.ow2.asm</groupId>
+                       <artifactId>asm-commons</artifactId>
+                       <scope>test</scope>
+               </dependency>
                <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>ajde</artifactId>
index 9e6831a2d34c7cbb958128dfe8bf37db47dc5490..8bc3c35bb2110bc090cd27df719125457eb60bad 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
     <dependency>
       <!-- Identical to lib/ant/lib/ant.jar, a former system-scoped dependency -->
       <groupId>ant</groupId>
index a15c3a53493141da55c6bb4725c5ef6079ceae30..d6975d22bcd64de19038e2b11e28171f90a9f302 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
index 38784790a76328c296a93a9ac39eaa6489d3d6e9..c5e082255f9f5d1739effdedeecd7c1a3530f72c 100644 (file)
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>testing-client</artifactId>
index 7a6bd3cd9eb8388e9a488c8a5c8b8055008d4166..33668d509bc1ed81e9088569a061ba17162e0b6e 100644 (file)
@@ -98,9 +98,15 @@ public class AntSpec implements ITestStep {
                        // setup aj.dir "modules" folder
                        p.setUserProperty("aj.root", new File("..").getAbsolutePath());
 
-                       // On Java 16+, LTW no longer works without this parameter. Add the argument here and not in AjcTestCase::run,
-                       // because even if 'useLTW' and 'useFullLTW' are not set, we might in the future have tests for weaver attachment
-                       // during runtime. See also docs/release/README-1.8.7.html.
+                       // On Java 16+, LTW did not work on AspectJ 1.9.7 to 1.9.21 without this parameter. So, we added the argument here
+                       // and not in AjcTestCase::run, because without 'useLTW' or 'useFullLTW', there might have been a need for weaver
+                       // attachment during runtime. See also docs/release/README-1.8.7.adoc.
+                       //
+                       // Since AspectJ 1.9.21.1, '--add-opens' is no longer necessary, because we found a workaround for defining
+                       // classes in arbitrary class loaders. But some tests, e.g. AtAjLTWTests.testLTWUnweavable, still use
+                       // ClassLoader::defineClass to inject dynamically generated classes into the current class loader. Therefore, we
+                       // still set the parameters, so they can be used on demand - not for LTW as such, but for class injection. See
+                       // also tests/java5/ataspectj/ataspectj/UnweavableTest.java.
                        //
                        // Attention: Ant 1.6.3 under Linux neither likes "" (empty string) nor " " (space), on Windows it would not be
                        // a problem. So we use "_dummy" Java system properties, even though they pollute the command line.
index 593c5b95772b0ccd323d01a09fecb6ba5d55bb00..4d7526f44aac511fde078b86e2be54c5d68469be 100644 (file)
@@ -68,14 +68,21 @@ public class RunSpec implements ITestStep {
 
                        if (vmargs == null)
                                vmargs = "";
-                       // On Java 16+, LTW no longer works without this parameter. Add the argument here and not in AjcTestCase::run,
-                       // because even if 'useLTW' and 'useFullLTW' are not set, we might in the future have tests for weaver attachment
-                       // during runtime. See also docs/release/README-1.8.7.html.
+                       // On Java 16+, LTW did not work on AspectJ 1.9.7 to 1.9.21 without this parameter. So, we added the argument here
+                       // and not in AjcTestCase::run, because without 'useLTW' or 'useFullLTW', there might have been a need for weaver
+                       // attachment during runtime. See also docs/release/README-1.8.7.adoc.
+                       //
+                       // Since AspectJ 1.9.21.1, '--add-opens' is no longer necessary, because we found a workaround for defining
+                       // classes in arbitrary class loaders. But some tests, e.g. AtAjLTWTests.testLTWUnweavable, still use
+                       // ClassLoader::defineClass to inject dynamically generated classes into the current class loader. Therefore, we
+                       // still set the parameters, so they can be used on demand - not for LTW as such, but for class injection. See
+                       // also tests/java5/ataspectj/ataspectj/UnweavableTest.java.
                        //
                        // The reason for setting this parameter for Java 9+ instead of 16+ is that it helps to avoid the JVM printing
                        // unwanted illegal access warnings during weaving in 'useFullLTW' mode, either making existing tests fail or
                        // having to assert on the warning messages.
-                       vmargs += is16VMOrGreater() ? " --add-opens java.base/java.lang=ALL-UNNAMED" : "";
+                       //
+                       // vmargs += is16VMOrGreater() ? " --add-opens java.base/java.lang=ALL-UNNAMED" : "";
 
                        AjcTestCase.RunResult rr = inTestCase.run(getClassToRun(), getModuleToRun(), args, vmargs, getClasspath(), getModulepath(), useLtw, "true".equalsIgnoreCase(usefullltw));
 
index 4f2dfb88553689661528dbb0ef0a8a71a97702bf..6ef88c87ba14f6965261e5251a5784c10fbeeb35 100644 (file)
@@ -15,8 +15,8 @@
             <jvmarg value="-Dorg.aspectj.weaver.Dump.condition=error"/>
                <sysproperty key="org.aspectj.dump.directory" path="${aj.sandbox}"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
 <!--
             <jvmarg value="-Dorg.aspectj.tracing.enabled=true"/>
index 73db721c9bd7be60078e7c31c9a17c15c00bd10b..0ad06667929ec2ff51ec899e0c29071bb6def37b 100644 (file)
@@ -19,8 +19,8 @@
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-Daj.weaving.verbose=true"/>
             <jvmarg value="-Dorg.aspectj.weaver.showWeaveInfo=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg value="-Dorg.aspectj.testing.server.debug=true"/>-->
                <arg path="${aj.sandbox}"/>
         </java>
index ca5dbc2543c9a5edfe96471f12685c4106b27cbe..74dac1409bc00dee53311aa0a37638417d812490 100644 (file)
@@ -20,8 +20,8 @@
             <jvmarg value="-Dorg.aspectj.tracing.enabled=true"/>
             <jvmarg value="-Dorg.aspectj.tracing.factory=default"/>
             <jvmarg value="-Dorg.aspectj.tracing.messages=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
index 9fa620572500b81976be2a9cadb086b6677466fd..285082612de7e782866a8231a4643be44a06e07b 100644 (file)
@@ -24,8 +24,8 @@
             <!-- use META-INF/aop.xml style -->
             <classpath path="ataspectj/pathentry"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
@@ -36,8 +36,8 @@
         <java fork="yes" classname="ataspectj.PerClauseTest" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>            -->
         </java>
     </target>
@@ -48,8 +48,8 @@
         <java fork="yes" classname="ataspectj.AroundInlineMungerTest" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <!--<jvmarg line="${jdwp}"/>--><!-- uncomment to debug with JDWP -->
         </java>
     </target>
@@ -60,8 +60,8 @@
         <java fork="yes" classname="ataspectj.AroundInlineMungerTest2" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
@@ -69,8 +69,8 @@
         <java fork="yes" classname="ataspectj.DumpTest" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
@@ -80,8 +80,8 @@
         <java fork="yes" classname="ataspectj.TestProxyGenerator" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
                 <pathelement path="${aj.sandbox}/main1.jar"/>
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
         <java fork="yes" classname="ataspectj.ltwlog.MainSilent" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
         <copy file="ataspectj/ltwlog/aop-verbsoe.xml"
               tofile="${aj.sandbox}/META-INF/aop.xml"
         <java fork="yes" classname="ataspectj.ltwlog.MainVerbose" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
         <copy file="ataspectj/ltwlog/aop-verboseandshow.xml"
               tofile="${aj.sandbox}/META-INF/aop.xml"
         <java fork="yes" classname="ataspectj.ltwlog.MainVerboseAndShow" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
                 <path refid="aj.path"/>
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
+            <!-- Necessary, because the test (not AspectJ itself!) uses ClassLoader::defineClass -->
             <jvmarg value="${aj.addOpensKey}"/>
             <jvmarg value="${aj.addOpensValue}"/>
         </java>
                 <path refid="aj.path"/>
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
 
         <copy file="ataspectj/aop-decptest.xml"
                 <path refid="aj.path"/>
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-          <jvmarg value="${aj.addOpensKey}"/>
-          <jvmarg value="${aj.addOpensValue}"/>
+<!--          <jvmarg value="${aj.addOpensKey}"/>-->
+<!--          <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
                 <path refid="aj.path"/>
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-DaspectDeclared=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
         <!--Now ensure that the error is not produced when the declaration is made.-->
         <copy file="ataspectj/ltwreweavable/aop-ltwreweavable-omitted.xml"
             </classpath>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-DaspectDeclared=false"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
             <classpath refid="aj.path"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-Daj.weaving.verbose=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
         </java>
     </target>
 
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-Daj.weaving.verbose=true"/>
             <jvmarg value="-Djava.util.logging.config.file=${aj.root}/weaver5/testdata/logging.properties"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
index 1ef9706127068e734220bf6e695684e004300972..50c877930364c2bacb1a89f8dc2be4572923c27b 100644 (file)
@@ -104,6 +104,8 @@ public class UnweavableTest extends TestCase {
 
         try {
             ClassLoader loader = this.getClass().getClassLoader();
+            // Needs "--add-opens java.base/java.lang=ALL-UNNAMED" on the JVM command line, injected in Ant build via
+            // aj.addOpensKey and aj.addOpensValue variables. See also AntSpec::execute.
             Method def = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
             def.setAccessible(true);
             Class<?> gen = (Class<?>) def.invoke(loader, "ataspectj.ISomeGen", cw.toByteArray(), 0, cw.toByteArray().length);
@@ -127,6 +129,8 @@ public class UnweavableTest extends TestCase {
 
         try {
             ClassLoader loader = this.getClass().getClassLoader();
+            // Needs "--add-opens java.base/java.lang=ALL-UNNAMED" on the JVM command line, injected in Ant build via
+            // aj.addOpensKey and aj.addOpensValue variables. See also AntSpec::execute.
             Method def = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
             def.setAccessible(true);
             Class<?> gen = (Class<?>) def.invoke(loader, "ataspectj.unmatched.Gen", cw.toByteArray(), 0, cw.toByteArray().length);
index c5f143fea504d9d98507635b09c8c05794679dba..d4958e3e3ea120e518fd2004a9703a1a7a071090 100644 (file)
@@ -14,8 +14,8 @@
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-Daj.weaving.verbose=true"/>
             <jvmarg value="-Dorg.aspectj.weaver.showWeaveInfo=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <!--<jvmarg value="-Dorg.aspectj.testing.server.debug=true"/>-->
             <sysproperty key="org.aspectj.dump.directory" path="${aj.sandbox}"/>
             <arg path="${aj.sandbox}"/>
@@ -30,8 +30,8 @@
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
             <jvmarg value="-Daj.weaving.verbose=true"/>
             <jvmarg value="-Dorg.aspectj.weaver.showWeaveInfo=true"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <!--<jvmarg value="-Dorg.aspectj.testing.server.debug=true"/>-->
             <sysproperty key="org.aspectj.dump.directory" path="${aj.sandbox}"/>
             <arg path="${aj.sandbox}"/>
index 0cae97a3670647b2bfc97e8a3c72ef3a70fd722c..abaf349d07893ec5f3691a7390d060343eab2731 100644 (file)
@@ -11,8 +11,8 @@
         <java fork="yes" classname="HelloWorldWithException" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <jvmarg value="-Dorg.aspectj.tracing.debug=true"/>
 <!--
             <jvmarg value="-Daj.weaving.verbose=true"/>
@@ -29,8 +29,8 @@
         <java fork="yes" classname="HelloWorldWithException" failonerror="yes">
             <classpath refid="aj.path"/>
             <jvmarg value="-Djava.system.class.loader=org.aspectj.weaver.loadtime.WeavingURLClassLoader"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <jvmarg value="-Dorg.aspectj.tracing.debug=true"/>
 <!--
             <jvmarg value="-Daj.weaving.verbose=true"/>
@@ -62,8 +62,8 @@
             <jvmarg value="-Dorg.aspectj.tracing.messages=true"/>
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
@@ -80,8 +80,8 @@
                     to bootclasspath -->
                <jvmarg value="-Xbootclasspath/p:${aj.sandbox}"/>
             <jvmarg value="-Xbootclasspath/a:${aj.bootpath}"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 
                <classpath>
                 <pathelement path="${aj.sandbox}/hello.jar:${aj.sandbox}/handler.jar:${aj.sandbox}/security.jar"/>
             <classpath refid="aj.path"/>
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
                <sysproperty key="org.aspectj.dump.directory" path="${aj.sandbox}"/>
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
             <jvmarg value="-Dorg.aspectj.tracing.factory=default"/>
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
index 65d6ddc7a71530cff72c68187582d709d7fcfec2..1489268b14f2dfd5968adc1e8d865c8f381e0900 100644 (file)
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                </dependency>
+               <dependency>
+                       <groupId>org.ow2.asm</groupId>
+                       <artifactId>asm-commons</artifactId>
+               </dependency>
                <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>weaver</artifactId>
index aa7db9d0e506ef7495331b73e362855f682fc76a..23a98c2ba1db5e4fb36e691738df1b4d7f9a5c8d 100644 (file)
                        <jvmarg value="${gc.args}"/>
                        <jvmarg value="${hprof.args}"/>
                        <jvmarg value="-javaagent:${aspectj.lib.dir}/aspectjweaver.jar"/>
-                       <jvmarg value="${aj.addOpensKey}"/>
-                       <jvmarg value="${aj.addOpensValue}"/>
+<!--                   <jvmarg value="${aj.addOpensKey}"/>-->
+<!--                   <jvmarg value="${aj.addOpensValue}"/>-->
                        <classpath>
                                <pathelement location="${results.dir}/ltw-app"/>
                                <pathelement location="${results.dir}/aspectlib.jar"/>
                        <arg value="${weave.injar}"/>
                        <jvmarg value="${gc.args}"/>
                        <jvmarg value="-javaagent:${aspectj.lib.dir}/aspectjweaver.jar"/>
-                       <jvmarg value="${aj.addOpensKey}"/>
-                       <jvmarg value="${aj.addOpensValue}"/>
+<!--                   <jvmarg value="${aj.addOpensKey}"/>-->
+<!--                   <jvmarg value="${aj.addOpensValue}"/>-->
                        <classpath>
                                <pathelement location="${results.dir}/ltw-app"/>
                                <pathelement location="${results.dir}/aspectlib.jar"/>
index 6e0ddd78e96061167be5e22de8118e19d66ecaff..687d41b10a30dc9570204565de525d4dabcbf4f1 100644 (file)
@@ -33,8 +33,8 @@
             <jvmarg value="-Dorg.aspectj.tracing.messages=true"/>
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
@@ -48,8 +48,8 @@
 <!--            <jvmarg value="-verbose:class"/>-->
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
@@ -63,8 +63,8 @@
             <jvmarg value="-Djava.util.logging.config.file=logging.properties"/>
             <!-- use META-INF/aop.xml style -->
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg line="${jdwp}"/>-->
         </java>
     </target>
@@ -76,8 +76,8 @@
             <jvmarg value="-Dorg.aspectj.tracing.factory=default"/>
             <jvmarg value="-Dorg.aspectj.tracing.messages=true"/>
             <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/>
-            <jvmarg value="${aj.addOpensKey}"/>
-            <jvmarg value="${aj.addOpensValue}"/>
+<!--            <jvmarg value="${aj.addOpensKey}"/>-->
+<!--            <jvmarg value="${aj.addOpensValue}"/>-->
 <!--            <jvmarg value="-verbose:class"/>-->
             <!-- use META-INF/aop.xml style -->
 <!--            <jvmarg line="${jdwp}"/>-->
index 657813b8d0599eb1128aac0a5dda6afd97aab745..f51e590e17b44298d9419eee5dd74592b9cff3e8 100644 (file)
@@ -65,5 +65,9 @@
       <groupId>org.ow2.asm</groupId>
       <artifactId>asm</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.ow2.asm</groupId>
+      <artifactId>asm-commons</artifactId>
+    </dependency>
   </dependencies>
 </project>