You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2016/08/03 01:56:07 UTC
[2/2] groovy git commit: GROOVY-7443: instantiating a class
withTraits does not use the classloader of the trait (test and formatting -
closes #34)
GROOVY-7443: instantiating a class withTraits does not use the classloader of the trait (test and formatting - closes #34)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/3d7e2cae
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/3d7e2cae
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/3d7e2cae
Branch: refs/heads/master
Commit: 3d7e2cae3b0f86c4cefd995349268ac3be7f5d3c
Parents: 03d3720
Author: paulk <pa...@asert.com.au>
Authored: Wed Aug 3 11:55:52 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Wed Aug 3 11:55:52 2016 +1000
----------------------------------------------------------------------
.../groovy/runtime/ProxyGeneratorAdapter.java | 182 +++++++++----------
.../util/ProxyGeneratorAdapterTest.groovy | 18 ++
2 files changed, 102 insertions(+), 98 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/3d7e2cae/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java b/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
index 2b09bdb..207a7ca 100644
--- a/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
+++ b/src/main/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
@@ -24,7 +24,6 @@ import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyRuntimeException;
import groovy.transform.Trait;
-
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
@@ -82,8 +81,6 @@ import java.util.concurrent.atomic.AtomicLong;
* Internally, the proxy generator makes use of ASM to generate bytecode, for improved performance as compared
* to the legacy proxy generation mechanism which made use of string templates.
*
- * @author Cedric Champeau
- *
* @since 2.0.0
*/
public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
@@ -130,13 +127,13 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
* Construct a proxy generator. This generator is used when we need to create a proxy object for a class or an
* interface given a map of closures.
*
- * @param closureMap the delegates implementations
- * @param superClass corresponding to the superclass class visitor
- * @param interfaces extra interfaces the proxy should implement
- * @param proxyLoader the class loader which should be used to load the generated proxy
+ * @param closureMap the delegates implementations
+ * @param superClass corresponding to the superclass class visitor
+ * @param interfaces extra interfaces the proxy should implement
+ * @param proxyLoader the class loader which should be used to load the generated proxy
* @param delegateClass if not null, generate a delegate field with the corresponding class
- * @param emptyBody if set to true, the unimplemented abstract methods will receive an empty body instead of
- * throwing an {@link UnsupportedOperationException}.
+ * @param emptyBody if set to true, the unimplemented abstract methods will receive an empty body instead of
+ * throwing an {@link UnsupportedOperationException}.
*/
public ProxyGeneratorAdapter(
final Map<Object, Object> closureMap,
@@ -146,9 +143,9 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
final boolean emptyBody,
final Class delegateClass) {
super(Opcodes.ASM4, new ClassWriter(0));
- this.loader = proxyLoader!=null?createInnerLoader(proxyLoader, interfaces):findClassLoader(superClass, interfaces);
+ this.loader = proxyLoader != null ? createInnerLoader(proxyLoader, interfaces) : findClassLoader(superClass, interfaces);
this.visitedMethods = new LinkedHashSet<Object>();
- this.delegatedClosures = closureMap.isEmpty()? EMPTY_DELEGATECLOSURE_MAP :new HashMap<String, Boolean>();
+ this.delegatedClosures = closureMap.isEmpty() ? EMPTY_DELEGATECLOSURE_MAP : new HashMap<String, Boolean>();
boolean wildcard = false;
for (Map.Entry<Object, Object> entry : closureMap.entrySet()) {
String name = entry.getKey().toString();
@@ -162,8 +159,8 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
Class fixedSuperClass = adjustSuperClass(superClass, interfaces);
// if we have to delegate to another object, generate the appropriate delegate field
// and collect the name of the methods for which delegation is active
- this.generateDelegateField = delegateClass!=null;
- this.objectDelegateMethods = generateDelegateField?createDelegateMethodList(fixedSuperClass, delegateClass, interfaces):EMPTY_STRING_SET;
+ this.generateDelegateField = delegateClass != null;
+ this.objectDelegateMethods = generateDelegateField ? createDelegateMethodList(fixedSuperClass, delegateClass, interfaces) : EMPTY_STRING_SET;
this.delegateClass = delegateClass;
// a proxy is supposed to be a concrete class, so it cannot extend an interface.
@@ -178,7 +175,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
classList.add(delegateClass);
Collections.addAll(this.classList, delegateClass.getInterfaces());
}
- if (interfaces!=null) {
+ if (interfaces != null) {
Collections.addAll(this.classList, interfaces);
}
this.proxyName = proxyName();
@@ -189,9 +186,9 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
this.visit(Opcodes.V1_5, ACC_PUBLIC, proxyName, null, null, null);
byte[] b = writer.toByteArray();
// CheckClassAdapter.verify(new ClassReader(b), true, new PrintWriter(System.err));
- cachedClass = loader.defineClass(proxyName.replace('/','.'), b);
+ cachedClass = loader.defineClass(proxyName.replace('/', '.'), b);
// cache no-arg constructor
- Class[] args = generateDelegateField?new Class[] { Map.class, delegateClass }:new Class[] { Map.class };
+ Class[] args = generateDelegateField ? new Class[]{Map.class, delegateClass} : new Class[]{Map.class};
Constructor constructor;
try {
constructor = cachedClass.getConstructor(args);
@@ -210,7 +207,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
Set<ClassNode> traits = new LinkedHashSet<ClassNode>();
// check if it's a trait
collectTraits(superClass, traits);
- if (interfaces!=null) {
+ if (interfaces != null) {
for (Class anInterface : interfaces) {
collectTraits(anInterface, traits);
}
@@ -220,7 +217,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
ClassNode cn = new ClassNode(name, ACC_PUBLIC | ACC_ABSTRACT, ClassHelper.OBJECT_TYPE, traits.toArray(new ClassNode[traits.size()]), null);
CompilationUnit cu = new CompilationUnit(loader);
CompilerConfiguration config = new CompilerConfiguration();
- SourceUnit su = new SourceUnit(name+"wrapper", "", config, loader, new ErrorCollector(config));
+ SourceUnit su = new SourceUnit(name + "wrapper", "", config, loader, new ErrorCollector(config));
cu.addSource(su);
cu.compile(Phases.CONVERSION);
su.getAST().addClass(cn);
@@ -229,7 +226,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
List<GroovyClass> classes = (List<GroovyClass>) cu.getClasses();
for (GroovyClass groovyClass : classes) {
if (groovyClass.getName().equals(name)) {
- return loader.defineClass(name,groovyClass.getBytes());
+ return loader.defineClass(name, groovyClass.getBytes());
}
}
}
@@ -238,7 +235,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
private static void collectTraits(final Class clazz, final Set<ClassNode> traits) {
Annotation annotation = clazz.getAnnotation(Trait.class);
- if (annotation!=null) {
+ if (annotation != null) {
ClassNode trait = ClassHelper.make(clazz);
traits.add(trait.getPlainNodeReference());
LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<ClassNode>();
@@ -261,7 +258,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
private InnerLoader findClassLoader(Class clazz, Class[] interfaces) {
ClassLoader cl = clazz.getClassLoader();
- if (cl==null) cl = this.getClass().getClassLoader();
+ if (cl == null) cl = this.getClass().getClassLoader();
return createInnerLoader(cl, interfaces);
}
@@ -270,13 +267,13 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
List<Method> interfaceMethods = new ArrayList<Method>();
List<Method> superClassMethods = new ArrayList<Method>();
Collections.addAll(superClassMethods, superClass.getDeclaredMethods());
- if (interfaces!=null) {
+ if (interfaces != null) {
for (Class thisInterface : interfaces) {
getInheritedMethods(thisInterface, interfaceMethods);
}
for (Method method : interfaceMethods) {
if (!(containsEquivalentMethod(superClassMethods, method))) {
- selectedMethods.add(method.getName()+Type.getMethodDescriptor(method));
+ selectedMethods.add(method.getName() + Type.getMethodDescriptor(method));
}
}
}
@@ -287,7 +284,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
if (!containsEquivalentMethod(interfaceMethods, method) &&
!containsEquivalentMethod(OBJECT_METHODS, method) &&
!containsEquivalentMethod(GROOVYOBJECT_METHODS, method)) {
- selectedMethods.add(method.getName()+Type.getMethodDescriptor(method));
+ selectedMethods.add(method.getName() + Type.getMethodDescriptor(method));
}
}
return selectedMethods;
@@ -357,6 +354,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
/**
* Visit every class/interface this proxy should implement, and generate the appropriate
* bytecode for delegation if available.
+ *
* @param clazz an class for which to generate bytecode
*/
private void visitClass(final Class clazz) {
@@ -393,7 +391,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
visitClass(intf);
}
Class superclass = clazz.getSuperclass();
- if (superclass!=null) visitClass(superclass);
+ if (superclass != null) visitClass(superclass);
// Ultimately, methods can be available in the closure map which are not defined by the superclass
// nor the interfaces
@@ -512,7 +510,6 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
mv.visitMaxs(2, 2);
mv.visitEnd();
}
-
}
/**
@@ -521,7 +518,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
private void addDelegateFields() {
visitField(ACC_PRIVATE + ACC_FINAL, CLOSURES_MAP_FIELD, "Ljava/util/Map;", null, null);
if (generateDelegateField) {
- visitField(ACC_PRIVATE+ACC_FINAL, DELEGATE_OBJECT_FIELD, BytecodeHelper.getTypeDescription(delegateClass), null, null);
+ visitField(ACC_PRIVATE + ACC_FINAL, DELEGATE_OBJECT_FIELD, BytecodeHelper.getTypeDescription(delegateClass), null, null);
}
}
@@ -552,13 +549,13 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
Object key = Arrays.asList(name, desc);
if (visitedMethods.contains(key)) return null;
- if (Modifier.isPrivate(access) || Modifier.isNative(access) || ((access&ACC_SYNTHETIC)!=0)) {
+ if (Modifier.isPrivate(access) || Modifier.isNative(access) || ((access & ACC_SYNTHETIC) != 0)) {
// do not generate bytecode for private methods
return null;
}
int accessFlags = access;
visitedMethods.add(key);
- if ((objectDelegateMethods.contains(name+desc) || delegatedClosures.containsKey(name) || (!"<init>".equals(name) && hasWildcard)) && !Modifier.isStatic(access) && !Modifier.isFinal(access)) {
+ if ((objectDelegateMethods.contains(name + desc) || delegatedClosures.containsKey(name) || (!"<init>".equals(name) && hasWildcard)) && !Modifier.isStatic(access) && !Modifier.isFinal(access)) {
if (!GROOVYOBJECT_METHOD_NAMESS.contains(name)) {
if (Modifier.isAbstract(access)) {
// prevents the proxy from being abstract
@@ -568,8 +565,8 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
delegatedClosures.put(name, Boolean.TRUE);
return makeDelegateToClosureCall(name, desc, signature, exceptions, accessFlags);
}
- if (generateDelegateField && objectDelegateMethods.contains(name+desc)) {
- return makeDelegateCall(name, desc, signature, exceptions, accessFlags);
+ if (generateDelegateField && objectDelegateMethods.contains(name + desc)) {
+ return makeDelegateCall(name, desc, signature, exceptions, accessFlags);
}
delegatedClosures.put(name, Boolean.TRUE);
return makeDelegateToClosureCall(name, desc, signature, exceptions, accessFlags);
@@ -588,24 +585,28 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
Type[] args = Type.getArgumentTypes(desc);
if (emptyBody) {
Type returnType = Type.getReturnType(desc);
- if (returnType==Type.VOID_TYPE) {
+ if (returnType == Type.VOID_TYPE) {
mv.visitInsn(RETURN);
} else {
int loadIns = getLoadInsn(returnType);
switch (loadIns) {
- case ILOAD: mv.visitInsn(ICONST_0);
+ case ILOAD:
+ mv.visitInsn(ICONST_0);
break;
- case LLOAD: mv.visitInsn(LCONST_0);
+ case LLOAD:
+ mv.visitInsn(LCONST_0);
break;
- case FLOAD: mv.visitInsn(FCONST_0);
+ case FLOAD:
+ mv.visitInsn(FCONST_0);
break;
- case DLOAD: mv.visitInsn(DCONST_0);
+ case DLOAD:
+ mv.visitInsn(DCONST_0);
break;
default:
mv.visitInsn(ACONST_NULL);
}
mv.visitInsn(getReturnInsn(returnType));
- mv.visitMaxs(2, registerLen(args)+1);
+ mv.visitMaxs(2, registerLen(args) + 1);
}
} else {
// for compatibility with the legacy proxy generator, we should throw an UnsupportedOperationException
@@ -614,7 +615,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "()V", false);
mv.visitInsn(ATHROW);
- mv.visitMaxs(2, registerLen(args)+1);
+ mv.visitMaxs(2, registerLen(args) + 1);
}
mv.visitEnd();
}
@@ -624,10 +625,10 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
private MethodVisitor createGetProxyTargetMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
MethodVisitor mv = super.visitMethod(ACC_PUBLIC | ACC_FINAL, name, desc, signature, exceptions);
mv.visitCode();
- mv.visitIntInsn(ALOAD,0);
+ mv.visitIntInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, proxyName, DELEGATE_OBJECT_FIELD, BytecodeHelper.getTypeDescription(delegateClass));
mv.visitInsn(ARETURN);
- mv.visitMaxs(1,1);
+ mv.visitMaxs(1, 1);
mv.visitEnd();
return null;
}
@@ -641,7 +642,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
}
private static int registerLen(final Type arg) {
- return arg== Type.DOUBLE_TYPE||arg==Type.LONG_TYPE?2:1;
+ return arg == Type.DOUBLE_TYPE || arg == Type.LONG_TYPE ? 2 : 1;
}
private MethodVisitor createConstructor(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
@@ -673,7 +674,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
}
mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass), "<init>", desc, false);
mv.visitInsn(RETURN);
- int max = idx + 1 + (generateDelegateField?1:0);
+ int max = idx + 1 + (generateDelegateField ? 1 : 0);
mv.visitMaxs(max, max);
mv.visitEnd();
return null;
@@ -696,9 +697,11 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
mv.visitFieldInsn(PUTFIELD, proxyName, DELEGATE_OBJECT_FIELD, BytecodeHelper.getTypeDescription(delegateClass));
}
- private static int getTypeArgsRegisterLength(Type[] args) {
+ private static int getTypeArgsRegisterLength(Type[] args) {
int length = 0;
- for (Type type : args) { length += registerLen(type); }
+ for (Type type : args) {
+ length += registerLen(type);
+ }
return length;
}
@@ -729,7 +732,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
} else {
mv.visitVarInsn(ALOAD, idx); // load argument i
}
- size = Math.max(size, 5+registerLen(arg));
+ size = Math.max(size, 5 + registerLen(arg));
idx += registerLen(arg);
mv.visitInsn(AASTORE); // store value into array
}
@@ -749,7 +752,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
// method body should be:
// this.$delegate$closure$methodName.call(new Object[] { method arguments })
Type[] args = Type.getArgumentTypes(desc);
- int arrayStore = args.length+1;
+ int arrayStore = args.length + 1;
BytecodeHelper.pushConstant(mv, args.length);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); // stack size = 1
stackSize = 1;
@@ -768,7 +771,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
mv.visitVarInsn(ALOAD, idx); // load argument i
}
idx += registerLen(arg);
- stackSize = Math.max(4, 3+registerLen(arg));
+ stackSize = Math.max(4, 3 + registerLen(arg));
mv.visitInsn(AASTORE); // store value into array
}
mv.visitVarInsn(ASTORE, arrayStore); // store array
@@ -795,7 +798,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
stackSize++;
mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Closure", "call", "([Ljava/lang/Object;)Ljava/lang/Object;", false); // call closure
unwrapResult(mv, desc);
- mv.visitMaxs(stackSize, arrayStore+1);
+ mv.visitMaxs(stackSize, arrayStore + 1);
mv.visitEnd();
// System.out.println("tmv.getText() = " + tmv.getText());
return null;
@@ -803,7 +806,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
private static void unwrapResult(final MethodVisitor mv, final String desc) {
Type returnType = Type.getReturnType(desc);
- if (returnType==Type.VOID_TYPE) {
+ if (returnType == Type.VOID_TYPE) {
mv.visitInsn(POP);
mv.visitInsn(RETURN);
} else {
@@ -817,8 +820,8 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
}
@SuppressWarnings("unchecked")
- public GroovyObject proxy(Map<Object,Object> map, Object... constructorArgs) {
- if (constructorArgs==null && cachedNoArgConstructor!=null) {
+ public GroovyObject proxy(Map<Object, Object> map, Object... constructorArgs) {
+ if (constructorArgs == null && cachedNoArgConstructor != null) {
// if there isn't any argument, we can make invocation faster using the cached constructor
try {
return (GroovyObject) cachedNoArgConstructor.newInstance(map);
@@ -830,16 +833,16 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
throw new GroovyRuntimeException(e);
}
}
- if (constructorArgs==null) constructorArgs= EMPTY_ARGS;
+ if (constructorArgs == null) constructorArgs = EMPTY_ARGS;
Object[] values = new Object[constructorArgs.length + 1];
System.arraycopy(constructorArgs, 0, values, 0, constructorArgs.length);
- values[values.length-1] = map;
+ values[values.length - 1] = map;
return DefaultGroovyMethods.<GroovyObject>newInstance(cachedClass, values);
}
@SuppressWarnings("unchecked")
- public GroovyObject delegatingProxy(Object delegate,Map<Object,Object> map, Object... constructorArgs) {
- if (constructorArgs==null && cachedNoArgConstructor!=null) {
+ public GroovyObject delegatingProxy(Object delegate, Map<Object, Object> map, Object... constructorArgs) {
+ if (constructorArgs == null && cachedNoArgConstructor != null) {
// if there isn't any argument, we can make invocation faster using the cached constructor
try {
return (GroovyObject) cachedNoArgConstructor.newInstance(map, delegate);
@@ -851,11 +854,11 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
throw new GroovyRuntimeException(e);
}
}
- if (constructorArgs==null) constructorArgs= EMPTY_ARGS;
+ if (constructorArgs == null) constructorArgs = EMPTY_ARGS;
Object[] values = new Object[constructorArgs.length + 2];
System.arraycopy(constructorArgs, 0, values, 0, constructorArgs.length);
- values[values.length-2] = map;
- values[values.length-1] = delegate;
+ values[values.length - 2] = map;
+ values[values.length - 1] = delegate;
return DefaultGroovyMethods.<GroovyObject>newInstance(cachedClass, values);
}
@@ -866,7 +869,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
*/
@SuppressWarnings("unchecked")
public static Closure ensureClosure(Object o) {
- if (o==null) throw new UnsupportedOperationException();
+ if (o == null) throw new UnsupportedOperationException();
if (o instanceof Closure) return (Closure) o;
return new ReturnValueWrappingClosure(o);
}
@@ -918,18 +921,17 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
throw new IllegalArgumentException("Unexpected type class [" + type + "]");
}
-
private static class InnerLoader extends GroovyClassLoader {
-
List<ClassLoader> internalClassLoaders = null;
protected InnerLoader(final ClassLoader parent, final Class[] interfaces) {
super(parent);
- if(interfaces != null) {
- for(Class c : interfaces) {
- if(c.getClassLoader() != parent) {
- if(internalClassLoaders == null) internalClassLoaders = new ArrayList<ClassLoader>(interfaces.length);
- if( ! internalClassLoaders.contains(c.getClassLoader()) ) {
+ if (interfaces != null) {
+ for (Class c : interfaces) {
+ if (c.getClassLoader() != parent) {
+ if (internalClassLoaders == null)
+ internalClassLoaders = new ArrayList<ClassLoader>(interfaces.length);
+ if (!internalClassLoaders.contains(c.getClassLoader())) {
internalClassLoaders.add(c.getClassLoader());
}
}
@@ -944,63 +946,47 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes {
public Class<?> loadClass(String name) throws ClassNotFoundException {
// First check whether it's already been loaded, if so use it
Class loadedClass = findLoadedClass(name);
-
+
if (loadedClass != null) return loadedClass;
-
- //check this class loader
+ // Check this class loader
try {
-
loadedClass = findClass(name);
-
- } catch (ClassNotFoundException e) { }
-
- if(loadedClass != null) return loadedClass;
+ } catch (ClassNotFoundException ignore) {
+ }
-
- //check parent classloader, keep the exception for future use
+ if (loadedClass != null) return loadedClass;
+
+ // Check parent classloader, keep the exception for future use
ClassNotFoundException ex = null;
try {
loadedClass = super.loadClass(name);
- } catch(ClassNotFoundException e) {
+ } catch (ClassNotFoundException e) {
ex = e;
}
-
+
if (loadedClass != null) return loadedClass;
-
-
- // Not loaded, try to load it
- if(internalClassLoaders != null) {
- for(ClassLoader i : internalClassLoaders) {
+ // Not loaded, try to load it
+ if (internalClassLoaders != null) {
+ for (ClassLoader i : internalClassLoaders) {
try {
// Ignore parent delegation and just try to load locally
-
loadedClass = i.loadClass(name);
-
- if(loadedClass != null) return loadedClass;
-
+ if (loadedClass != null) return loadedClass;
} catch (ClassNotFoundException e) {
// Swallow exception - does not exist locally
}
-
}
-
}
-
- //throw parent exception if exists, otherwise create a new exception
- if(ex != null) throw ex;
-
+ // Throw earlier exception from parent loader if it exists, otherwise create a new exception
+ if (ex != null) throw ex;
throw new ClassNotFoundException(name);
-
}
-
}
-
-
- private static class ReturnValueWrappingClosure<V> extends Closure<V>{
+ private static class ReturnValueWrappingClosure<V> extends Closure<V> {
private final V value;
public ReturnValueWrappingClosure(V returnValue) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/3d7e2cae/src/test/groovy/util/ProxyGeneratorAdapterTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/util/ProxyGeneratorAdapterTest.groovy b/src/test/groovy/util/ProxyGeneratorAdapterTest.groovy
index 393dad4..a9d2fc9 100644
--- a/src/test/groovy/util/ProxyGeneratorAdapterTest.groovy
+++ b/src/test/groovy/util/ProxyGeneratorAdapterTest.groovy
@@ -172,6 +172,24 @@ class ProxyGeneratorAdapterTest extends GroovyTestCase {
'''
}
+ static class ClassA {}
+ static trait Trait1 { def method1() { 'Trait1 method' } }
+
+ // GROOVY-7443
+ void testTraitFromDifferentClassloader() {
+ def aWith1 = new ClassA().withTraits(Trait1)
+ assert aWith1.method1() == 'Trait1 method'
+ GroovyClassLoader gcl = new GroovyClassLoader(Thread.currentThread().contextClassLoader)
+ Class classB = gcl.parseClass('class ClassB {}')
+ Class trait2 = gcl.parseClass('trait Trait2 { def method2() { "Trait2 method" } }')
+ def bWith1 = classB.newInstance().withTraits(Trait1)
+ assert bWith1.method1() == 'Trait1 method'
+ def bWith2 = classB.newInstance().withTraits(trait2)
+ assert bWith2.method2() == 'Trait2 method'
+ def aWith2 = new ClassA().withTraits(trait2)
+ assert aWith2.method2() == 'Trait2 method'
+ }
+
void testGetTypeArgsRegisterLength() {
def types = { list -> list as org.objectweb.asm.Type[] }
def proxyGeneratorAdapter = new ProxyGeneratorAdapter([:], Object, [] as Class[], null, false, Object)