diff options
author | Andy Clement <aclement@pivotal.io> | 2018-09-29 07:47:57 -0700 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2018-09-29 07:47:57 -0700 |
commit | f6d9aaaf05eca3aaf06d3a769a83f302b0501dca (patch) | |
tree | f2f8b3c99f0bd2a77a570f1bf230c2d7aca23647 /loadtime | |
parent | 8aeb774d210a42240f2d6d89dd89e947a084fd7f (diff) | |
download | aspectj-f6d9aaaf05eca3aaf06d3a769a83f302b0501dca.tar.gz aspectj-f6d9aaaf05eca3aaf06d3a769a83f302b0501dca.zip |
1.9.2.RC1 changesV1_9_2_RC1
Diffstat (limited to 'loadtime')
-rw-r--r-- | loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java | 159 | ||||
-rw-r--r-- | loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java | 4 |
2 files changed, 131 insertions, 32 deletions
diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java index 6fa259d03..b22f870f0 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java @@ -11,7 +11,12 @@ 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.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.security.ProtectionDomain; @@ -1043,49 +1048,145 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { return unsafe; } - private void defineClass(ClassLoader loader, String name, byte[] bytes) { - if (trace.isTraceEnabled()) { - trace.enter("defineClass", this, new Object[] { loader, name, bytes }); - } - Object clazz = null; - debug("generating class '" + name + "'"); + private static Method bindTo_Method, invokeWithArguments_Method = null; + private static Object defineClassMethodHandle = null; + + private static Boolean initializedForJava11 = false; + + // 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; try { - clazz = getUnsafe().defineClass(name, bytes, 0, bytes.length, loader, null); - } 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 + // MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.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}); + + // 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, baseLookup); + 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(System.err); - warn("define generated class failed", e); - } - - if (trace.isTraceEnabled()) { - trace.exit("defineClass", clazz); + e.printStackTrace(); } } - + private void defineClass(ClassLoader loader, String name, byte[] bytes, ProtectionDomain protectionDomain) { if (trace.isTraceEnabled()) { - trace.enter("defineClass", this, new Object[] { loader, name, bytes, protectionDomain }); + trace.enter("defineClass", this, new Object[] { loader, name, bytes }); } 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 (LangUtil.is11VMOrGreater()) { + try { + if (!initializedForJava11) { + initializeForJava11(); + } + // Do this: clazz = defineClassMethodHandle.bindTo(loader).invokeWithArguments(name, bytes, 0, bytes.length); + Object o = bindTo_Method.invoke(defineClassMethodHandle,loader); + clazz = invokeWithArguments_Method.invoke(o, new Object[] {new Object[] {name, bytes, 0, bytes.length}}); + + } 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); + } } if (trace.isTraceEnabled()) { trace.exit("defineClass", clazz); } } + static Method defineClassMethod; + private static String lock = "lock"; + + +// /* +// 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) { + } +// 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); +// } +// } }
\ No newline at end of file diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java index c0fd9d342..92201083f 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ConcreteAspectCodeGen.java @@ -355,9 +355,7 @@ public class ConcreteAspectCodeGen { } /** - * Build the bytecode for the concrete aspect - * - * @return concrete aspect bytecode + * @return the bytecode for the concrete aspect */ public byte[] getBytes() { if (!isValid) { |