This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 86d4cb7665 Trivial tweak for `ProxyGenerator[Adaptor]`
86d4cb7665 is described below
commit 86d4cb76654d339f9e7351388aead47a21f53b22
Author: Daniel Sun <[email protected]>
AuthorDate: Sat Jan 11 23:45:34 2025 +0900
Trivial tweak for `ProxyGenerator[Adaptor]`
---
src/main/java/groovy/util/ProxyGenerator.java | 82 +++++++++++-----------
.../groovy/runtime/ProxyGeneratorAdapter.java | 59 +++++++---------
2 files changed, 65 insertions(+), 76 deletions(-)
diff --git a/src/main/java/groovy/util/ProxyGenerator.java
b/src/main/java/groovy/util/ProxyGenerator.java
index 92a4cd00d3..d8c8f523c8 100644
--- a/src/main/java/groovy/util/ProxyGenerator.java
+++ b/src/main/java/groovy/util/ProxyGenerator.java
@@ -57,21 +57,22 @@ public class ProxyGenerator {
setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(ProxyGenerator.class));
}
- public static final ProxyGenerator INSTANCE = new ProxyGenerator(); //
TODO: Should we make ProxyGenerator singleton?
+ public static final ProxyGenerator INSTANCE = new ProxyGenerator();
/**
* Caches proxy classes. When, for example, a call like: <code>map as
MyClass</code>
* is found, then a lookup is made into the cache to find if a suitable
adapter
* exists already. If so, it is reused instead of generating a new one.
*/
- private final Map<CacheKey,ProxyGeneratorAdapter> adapterCache;
-
+ private final Map<CacheKey, ProxyGeneratorAdapter> adapterCache;
+ private static final int CACHE_SIZE =
Integer.getInteger("groovy.adapter.cache.default.size", 64);
+ private static final float LOAD_FACTOR = 0.75f;
+ private static final int INIT_CAPACITY = (int) Math.ceil(CACHE_SIZE /
LOAD_FACTOR) + 1;
{
- final int cache_size =
Integer.getInteger("groovy.adapter.cache.default.size", 64);
- float load_factor = 0.75f; int init_capacity = (int)
Math.ceil(cache_size / load_factor) + 1;
- adapterCache = new LinkedHashMap<CacheKey,
ProxyGeneratorAdapter>(init_capacity, load_factor, true) {
- @Override protected boolean removeEldestEntry(Map.Entry<CacheKey,
ProxyGeneratorAdapter> entry) {
- return size() > cache_size;
+ adapterCache = new LinkedHashMap<>(INIT_CAPACITY, LOAD_FACTOR, true) {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<CacheKey,
ProxyGeneratorAdapter> entry) {
+ return size() > CACHE_SIZE;
}
};
}
@@ -80,6 +81,8 @@ public class ProxyGenerator {
private boolean emptyMethods;
private ClassLoader override;
+ // private ProxyGenerator() {} // TODO: Should we make ProxyGenerator
singleton?
+
public boolean getDebug() {
return debug;
}
@@ -130,7 +133,7 @@ public class ProxyGenerator {
}
public GroovyObject instantiateAggregateFromBaseClass(Closure cl, Class
clazz) {
- Map<String, Closure> m = new HashMap<String, Closure>();
+ Map<String, Closure> m = new HashMap<>(4);
m.put("*", cl);
return instantiateAggregateFromBaseClass(m, clazz, null);
}
@@ -148,7 +151,7 @@ public class ProxyGenerator {
}
public GroovyObject instantiateAggregateFromInterface(Map map, Class
clazz) {
- List<Class> interfaces = new ArrayList<Class>();
+ List<Class> interfaces = new ArrayList<>(2);
interfaces.add(clazz);
return instantiateAggregate(map, interfaces);
}
@@ -169,7 +172,7 @@ public class ProxyGenerator {
if (clazz != null && Modifier.isFinal(clazz.getModifiers())) {
throw new GroovyCastException("Cannot coerce a map to class " +
clazz.getName() + " because it is a final class");
}
- Map<Object,Object> map = closureMap != null ? closureMap :
EMPTY_CLOSURE_MAP;
+ Map<Object, Object> map = closureMap != null ? closureMap :
EMPTY_CLOSURE_MAP;
ProxyGeneratorAdapter adapter = createAdapter(map, interfaces, null,
clazz);
return adapter.proxy(map, constructorArgs);
@@ -206,27 +209,28 @@ public class ProxyGenerator {
* @return a proxy object implementing the specified interfaces, and
delegating to the provided object
*/
public GroovyObject instantiateDelegateWithBaseClass(Map closureMap,
List<Class> interfaces, Object delegate, Class baseClass, String name) {
- Map<Object,Object> map = closureMap != null ? closureMap :
EMPTY_CLOSURE_MAP;
+ Map<Object, Object> map = closureMap != null ? closureMap :
EMPTY_CLOSURE_MAP;
ProxyGeneratorAdapter adapter = createAdapter(map, interfaces,
delegate.getClass(), baseClass);
- return adapter.delegatingProxy(delegate, map, (Object[])null);
+ return adapter.delegatingProxy(delegate, map, (Object[]) null);
}
private ProxyGeneratorAdapter createAdapter(final Map<Object,Object>
closureMap, final List<Class> interfaceList, final Class delegateClass, final
Class baseClass) {
Class[] interfaces = interfaceList != null ?
interfaceList.toArray(EMPTY_CLASS_ARRAY) : EMPTY_CLASS_ARRAY;
- final Class base = baseClass != null ? baseClass : (interfaces.length
> 0 ? interfaces[0] : Object.class);
- Set<String> methodNames = closureMap.isEmpty() ?
Collections.emptySet() : new HashSet<>();
+ final Class<?> base = baseClass != null ? baseClass :
(interfaces.length > 0 ? interfaces[0] : Object.class);
+ final int closureMapSize = closureMap.size();
+ Set<String> methodNames = closureMapSize == 0 ? Collections.emptySet()
: new HashSet<>(closureMapSize);
for (Object key : closureMap.keySet()) {
methodNames.add(key.toString());
}
boolean useDelegate = (delegateClass != null);
CacheKey key = new CacheKey(base, useDelegate ? delegateClass :
Object.class, methodNames, interfaces, emptyMethods, useDelegate);
+ ClassLoader classLoader = useDelegate ? delegateClass.getClassLoader()
: base.getClassLoader();
synchronized (adapterCache) {
- return adapterCache.computeIfAbsent(key, k -> {
- ClassLoader classLoader = useDelegate ?
delegateClass.getClassLoader() : base.getClassLoader();
- return new ProxyGeneratorAdapter(closureMap, base, interfaces,
classLoader, emptyMethods, useDelegate ? delegateClass : null);
- });
+ return adapterCache.computeIfAbsent(key,
+ k -> new ProxyGeneratorAdapter(closureMap, base,
interfaces, classLoader, emptyMethods,
+
useDelegate ? delegateClass : null));
}
}
@@ -250,29 +254,32 @@ public class ProxyGenerator {
if (Traits.isTrait(o2)) return 1;
return o1.getName().compareTo(o2.getName());
};
- private final boolean emptyMethods;
- private final boolean useDelegate;
- private final Set<String> methods;
- private final ClassReference delegateClass;
private final ClassReference baseClass;
+ private final ClassReference delegateClass;
+ private final Set<String> methods;
private final ClassReference[] interfaces;
+ private final boolean emptyMethods;
+ private final boolean useDelegate;
private CacheKey(final Class baseClass, final Class delegateClass,
final Set<String> methods, final Class[] interfaces, final boolean
emptyMethods, final boolean useDelegate) {
- this.useDelegate = useDelegate;
this.baseClass = new ClassReference(baseClass);
this.delegateClass = new ClassReference(delegateClass);
+ this.methods = methods;
this.emptyMethods = emptyMethods;
- this.interfaces = interfaces == null ? null : new
ClassReference[interfaces.length];
+ this.useDelegate = useDelegate;
+ final int interfaceCount = interfaces.length;
if (interfaces != null) {
- Class[] interfacesCopy = new Class[interfaces.length];
- System.arraycopy(interfaces, 0, interfacesCopy, 0,
interfaces.length);
+ Class[] interfacesCopy = new Class[interfaceCount];
+ System.arraycopy(interfaces, 0, interfacesCopy, 0,
interfaceCount);
Arrays.sort(interfacesCopy, INTERFACE_COMPARATOR);
- for (int i = 0; i < interfacesCopy.length; i++) {
- Class anInterface = interfacesCopy[i];
- this.interfaces[i] = new ClassReference(anInterface);
+ ClassReference[] interfaceReferences = new
ClassReference[interfaceCount];
+ for (int i = 0, n = interfacesCopy.length; i < n; i++) {
+ interfaceReferences[i] = new
ClassReference(interfacesCopy[i]);
}
+ this.interfaces = interfaceReferences;
+ } else {
+ this.interfaces = null;
}
- this.methods = methods;
}
@Override
@@ -284,8 +291,8 @@ public class ProxyGenerator {
if (emptyMethods != cacheKey.emptyMethods) return false;
if (useDelegate != cacheKey.useDelegate) return false;
- if (!Objects.equals(baseClass, cacheKey.baseClass)) return false;
if (!Objects.equals(delegateClass, cacheKey.delegateClass)) return
false;
+ if (!Objects.equals(baseClass, cacheKey.baseClass)) return false;
if (!Arrays.equals(interfaces, cacheKey.interfaces)) return false;
if (!Objects.equals(methods, cacheKey.methods)) return false;
@@ -294,20 +301,13 @@ public class ProxyGenerator {
@Override
public int hashCode() {
- int result = (emptyMethods ? 1 : 0);
- result = 31 * result + (useDelegate ? 1 : 0);
- result = 31 * result + (methods != null ? methods.hashCode() : 0);
- result = 31 * result + (baseClass != null ? baseClass.hashCode() :
0);
- result = 31 * result + (delegateClass != null ?
delegateClass.hashCode() : 0);
- result = 31 * result + (interfaces != null ?
Arrays.hashCode(interfaces) : 0);
- return result;
+ return Objects.hash(emptyMethods, useDelegate, delegateClass,
baseClass, Arrays.hashCode(interfaces), methods);
}
/**
* A weak reference which delegates equals and hashcode to the
referent.
*/
private static class ClassReference extends WeakReference<Class> {
-
public ClassReference(Class referent) {
super(referent);
}
@@ -317,8 +317,8 @@ public class ProxyGenerator {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Class thisClass = this.get();
- ClassReference that = (ClassReference) o;
if (thisClass == null) return false;
+ ClassReference that = (ClassReference) o;
return thisClass.equals(that.get());
}
diff --git
a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
index f6aa433001..920909a304 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
@@ -123,7 +123,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
private static final String CLOSURES_MAP_FIELD = "$closures$delegate$map";
private static final String DELEGATE_OBJECT_FIELD = "$delegate";
- private static final AtomicLong proxyCounter = new AtomicLong();
+ private static final AtomicLong PROXY_COUNTER = new AtomicLong();
private static final List<Method> OBJECT_METHODS =
getInheritedMethods(Object.class, new ArrayList<>());
private static final List<Method> GROOVYOBJECT_METHODS =
getInheritedMethods(GroovyObject.class, new ArrayList<>());
@@ -349,7 +349,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
Class<?>[] candidateParamTypes = candidate.getParameterTypes();
Class<?>[] methodParamTypes = method.getParameterTypes();
if (candidateParamTypes.length != methodParamTypes.length) return
false;
- for (int i = 0; i < methodParamTypes.length; i++) {
+ for (int i = 0, n = methodParamTypes.length; i < n; i++) {
if (!candidateParamTypes[i].equals(methodParamTypes[i])) return
false;
}
return true;
@@ -401,16 +401,16 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
exceptions);
}
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
- for (Constructor<?> method : constructors) {
- Class<?>[] exceptionTypes = method.getExceptionTypes();
+ for (Constructor<?> constructor : constructors) {
+ Class<?>[] exceptionTypes = constructor.getExceptionTypes();
String[] exceptions = new String[exceptionTypes.length];
for (int i = 0; i < exceptions.length; i++) {
exceptions[i] =
BytecodeHelper.getClassInternalName(exceptionTypes[i]);
}
- // for each method defined in the class, generate the appropriate
delegation bytecode
- visitMethod(method.getModifiers(),
+ // for each constructor defined in the class, generate the
appropriate delegation bytecode
+ visitMethod(constructor.getModifiers(),
"<init>",
- BytecodeHelper.getMethodDescriptor(Void.TYPE,
method.getParameterTypes()),
+ BytecodeHelper.getMethodDescriptor(Void.TYPE,
constructor.getParameterTypes()),
null,
exceptions);
}
@@ -447,14 +447,10 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
{
mv = super.visitMethod(ACC_PUBLIC, "getMetaClass",
"()Lgroovy/lang/MetaClass;", null, null);
mv.visitCode();
- Label l0 = new Label();
- mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, proxyName, "metaClass",
"Lgroovy/lang/MetaClass;");
Label l1 = new Label();
mv.visitJumpInsn(IFNONNULL, l1);
- Label l2 = new Label();
- mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass",
"()Ljava/lang/Class;", false);
@@ -472,16 +468,10 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
{
mv = super.visitMethod(ACC_PUBLIC, "setMetaClass",
"(Lgroovy/lang/MetaClass;)V", null, null);
mv.visitCode();
- Label l0 = new Label();
- mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, proxyName, "metaClass",
"Lgroovy/lang/MetaClass;");
- Label l1 = new Label();
- mv.visitLabel(l1);
mv.visitInsn(RETURN);
- Label l2 = new Label();
- mv.visitLabel(l2);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
@@ -491,7 +481,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
* Creates delegate fields for every closure defined in the map.
*/
private void addDelegateFields() {
- visitField(ACC_PRIVATE + ACC_FINAL, CLOSURES_MAP_FIELD,
"Ljava/util/Map;", null, null);
+ 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);
}
@@ -503,8 +493,8 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
name = name.substring(1, name.length() - 1) + "_array";
}
int index = name.lastIndexOf('.');
- if (index == -1) return name + proxyCounter.incrementAndGet() +
"_groovyProxy";
- return name.substring(index + 1) + proxyCounter.incrementAndGet() +
"_groovyProxy";
+ if (index == -1) return name + PROXY_COUNTER.incrementAndGet() +
"_groovyProxy";
+ return name.substring(index + 1) + PROXY_COUNTER.incrementAndGet() +
"_groovyProxy";
}
private static boolean isImplemented(final Class<?> clazz, final String
name, final String desc) {
@@ -546,10 +536,8 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
}
} else if ("getProxyTarget".equals(name) &&
"()Ljava/lang/Object;".equals(desc)) {
return createGetProxyTargetMethod(access, name, desc, signature,
exceptions);
-
} else if ("<init>".equals(name) && (Modifier.isPublic(access) ||
Modifier.isProtected(access))) {
return createConstructor(access, name, desc, signature,
exceptions);
-
} else if (Modifier.isAbstract(access) &&
!GROOVYOBJECT_METHOD_NAMES.contains(name) && !isImplemented(superClass, name,
desc)) {
MethodVisitor mv = super.visitMethod(access & ~ACC_ABSTRACT, name,
desc, signature, exceptions);
mv.visitCode();
@@ -683,14 +671,14 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
mv.visitVarInsn(ALOAD, 0); // load this
mv.visitFieldInsn(GETFIELD, proxyName, DELEGATE_OBJECT_FIELD,
BytecodeHelper.getTypeDescription(delegateClass)); // load delegate
// using InvokerHelper to allow potential intercepted calls
- int size;
mv.visitLdcInsn(name); // method name
Type[] args = Type.getArgumentTypes(desc);
- BytecodeHelper.pushConstant(mv, args.length);
+ final int argCount = args.length;
+ BytecodeHelper.pushConstant(mv, argCount);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
- size = 6;
+ int size = 6;
int idx = 1;
- for (int i = 0; i < args.length; i++) {
+ for (int i = 0; i < argCount; i++) {
Type arg = args[i];
mv.visitInsn(DUP);
BytecodeHelper.pushConstant(mv, i);
@@ -703,7 +691,6 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
mv.visitMethodInsn(INVOKESTATIC,
"org/codehaus/groovy/runtime/InvokerHelper", "invokeMethod",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;",
false);
unwrapResult(mv, desc);
mv.visitMaxs(0, 0);
-
return mv;
}
@@ -715,11 +702,12 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
// method body should be:
// this.$delegate$closure$methodName.call(new Object[] { method
arguments })
Type[] args = Type.getArgumentTypes(desc);
- int arrayStore = args.length + 1;
- BytecodeHelper.pushConstant(mv, args.length);
+ final int argCount = args.length;
+ int arrayStore = argCount + 1;
+ BytecodeHelper.pushConstant(mv, argCount);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); // stack size = 1
int idx = 1;
- for (int i = 0; i < args.length; i++) {
+ for (int i = 0; i < argCount; i++) {
Type arg = args[i];
mv.visitInsn(DUP); // stack size = 2
BytecodeHelper.pushConstant(mv, i); // array index, stack size = 3
@@ -753,7 +741,6 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
unwrapResult(mv, desc);
mv.visitMaxs(0, 0);
mv.visitEnd();
-// System.out.println("tmv.getText() = " + tmv.getText());
return null;
}
@@ -793,8 +780,9 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
}
}
if (constructorArgs == null) constructorArgs = EMPTY_ARGS;
- Object[] values = new Object[constructorArgs.length + 1];
- System.arraycopy(constructorArgs, 0, values, 0,
constructorArgs.length);
+ final int constructorArgCount = constructorArgs.length;
+ Object[] values = new Object[constructorArgCount + 1];
+ System.arraycopy(constructorArgs, 0, values, 0, constructorArgCount);
values[values.length - 1] = map;
return DefaultGroovyMethods.<GroovyObject>newInstance(cachedClass,
values);
}
@@ -810,8 +798,9 @@ public class ProxyGeneratorAdapter extends ClassVisitor {
}
}
if (constructorArgs == null) constructorArgs = EMPTY_ARGS;
- Object[] values = new Object[constructorArgs.length + 2];
- System.arraycopy(constructorArgs, 0, values, 0,
constructorArgs.length);
+ final int constructorArgCount = constructorArgs.length;
+ Object[] values = new Object[constructorArgCount + 2];
+ System.arraycopy(constructorArgs, 0, values, 0, constructorArgCount);
values[values.length - 2] = map;
values[values.length - 1] = delegate;
return DefaultGroovyMethods.<GroovyObject>newInstance(cachedClass,
values);