aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--javassist.jarbin699781 -> 700680 bytes
-rw-r--r--src/main/javassist/util/proxy/MethodHandler.java4
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java112
-rw-r--r--src/main/javassist/util/proxy/RuntimeSupport.java34
-rw-r--r--src/test/javassist/JvstTest.java4
-rw-r--r--src/test/javassist/proxyfactory/ProxyFactoryTest.java2
-rw-r--r--src/test/test/javassist/proxy/ProxySimpleTest.java38
7 files changed, 128 insertions, 66 deletions
diff --git a/javassist.jar b/javassist.jar
index 87393d38..6cd27e1c 100644
--- a/javassist.jar
+++ b/javassist.jar
Binary files differ
diff --git a/src/main/javassist/util/proxy/MethodHandler.java b/src/main/javassist/util/proxy/MethodHandler.java
index 9145895a..2cd8fb16 100644
--- a/src/main/javassist/util/proxy/MethodHandler.java
+++ b/src/main/javassist/util/proxy/MethodHandler.java
@@ -22,7 +22,7 @@ import java.lang.reflect.Method;
* The interface implemented by the invocation handler of a proxy
* instance.
*
- * @see ProxyFactory#setHandler(MethodHandler)
+ * @see Proxy#setHandler(MethodHandler)
*/
public interface MethodHandler {
/**
@@ -33,7 +33,7 @@ public interface MethodHandler {
* @param thisMethod the overridden method declared in the super
* class or interface.
* @param proceed the forwarder method for invoking the overridden
- * method. It is null if the overridden mehtod is
+ * method. It is null if the overridden method is
* abstract or declared in the interface.
* @param args an array of objects containing the values of
* the arguments passed in the method invocation
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java
index 9bce51fa..957ba8f1 100644
--- a/src/main/javassist/util/proxy/ProxyFactory.java
+++ b/src/main/javassist/util/proxy/ProxyFactory.java
@@ -27,6 +27,7 @@ import java.util.*;
import java.lang.ref.WeakReference;
import javassist.CannotCompileException;
+import javassist.NotFoundException;
import javassist.bytecode.*;
/*
@@ -204,7 +205,7 @@ public class ProxyFactory {
private static final String SERIAL_VERSION_UID_FIELD = "serialVersionUID";
private static final String SERIAL_VERSION_UID_TYPE = "J";
- private static final int SERIAL_VERSION_UID_VALUE = -1;
+ private static final long SERIAL_VERSION_UID_VALUE = -1L;
/**
* If true, a generated proxy class is cached and it will be reused
@@ -736,8 +737,10 @@ public class ProxyFactory {
// HashMap allMethods = getMethods(superClass, interfaces);
// int size = allMethods.size();
makeConstructors(classname, cf, pool, classname);
- int s = overrideMethods(cf, pool, classname);
- addMethodsHolder(cf, pool, classname, s);
+
+ ArrayList forwarders = new ArrayList();
+ int s = overrideMethods(cf, pool, classname, forwarders);
+ addClassInitializer(cf, pool, classname, s, forwarders);
addSetter(classname, cf, pool);
if (!hasGetHandler)
addGetter(classname, cf, pool);
@@ -875,8 +878,8 @@ public class ProxyFactory {
cf.setInterfaces(list);
}
- private static void addMethodsHolder(ClassFile cf, ConstPool cp,
- String classname, int size)
+ private static void addClassInitializer(ClassFile cf, ConstPool cp,
+ String classname, int size, ArrayList forwarders)
throws CannotCompileException
{
FieldInfo finfo = new FieldInfo(cp, HOLDER, HOLDER_TYPE);
@@ -884,18 +887,61 @@ public class ProxyFactory {
cf.addField(finfo);
MethodInfo minfo = new MethodInfo(cp, "<clinit>", "()V");
minfo.setAccessFlags(AccessFlag.STATIC);
- Bytecode code = new Bytecode(cp, 0, 0);
+ setThrows(minfo, cp, new Class[] { ClassNotFoundException.class });
+
+ Bytecode code = new Bytecode(cp, 0, 2);
code.addIconst(size * 2);
code.addAnewarray("java.lang.reflect.Method");
+ final int varArray = 0;
+ code.addAstore(varArray);
+
+ // forName() must be called here. Otherwise, the class might be
+ // invisible.
+ code.addLdc(classname);
+ code.addInvokestatic("java.lang.Class",
+ "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
+ final int varClass = 1;
+ code.addAstore(varClass);
+
+ Iterator it = forwarders.iterator();
+ while (it.hasNext()) {
+ Find2MethodsArgs args = (Find2MethodsArgs)it.next();
+ callFind2Methods(code, args.methodName, args.delegatorName,
+ args.origIndex, args.descriptor, varClass, varArray);
+ }
+
+ code.addAload(varArray);
code.addPutstatic(classname, HOLDER, HOLDER_TYPE);
- // also need to set serial version uid
- code.addLconst(-1L);
+
+ code.addLconst(SERIAL_VERSION_UID_VALUE);
code.addPutstatic(classname, SERIAL_VERSION_UID_FIELD, SERIAL_VERSION_UID_TYPE);
code.addOpcode(Bytecode.RETURN);
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
}
+ /**
+ * @param thisMethod might be null.
+ */
+ private static void callFind2Methods(Bytecode code, String superMethod, String thisMethod,
+ int index, String desc, int classVar, int arrayVar) {
+ String findClass = RuntimeSupport.class.getName();
+ String findDesc
+ = "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V";
+
+ code.addAload(classVar);
+ code.addLdc(superMethod);
+ if (thisMethod == null)
+ code.addOpcode(Opcode.ACONST_NULL);
+ else
+ code.addLdc(thisMethod);
+
+ code.addIconst(index);
+ code.addLdc(desc);
+ code.addAload(arrayVar);
+ code.addInvokestatic(findClass, "find2Methods", findDesc);
+ }
+
private static void addSetter(String classname, ClassFile cf, ConstPool cp)
throws CannotCompileException
{
@@ -925,7 +971,7 @@ public class ProxyFactory {
cf.addMethod(minfo);
}
- private int overrideMethods(ClassFile cf, ConstPool cp, String className)
+ private int overrideMethods(ClassFile cf, ConstPool cp, String className, ArrayList forwarders)
throws CannotCompileException
{
String prefix = makeUniqueName("_d", signatureMethods);
@@ -938,7 +984,7 @@ public class ProxyFactory {
int mod = meth.getModifiers();
if (testBit(signature, index)) {
override(className, meth, prefix, index,
- keyToDesc(key, meth), cf, cp);
+ keyToDesc(key, meth), cf, cp, forwarders);
}
index++;
}
@@ -947,7 +993,7 @@ public class ProxyFactory {
}
private void override(String thisClassname, Method meth, String prefix,
- int index, String desc, ClassFile cf, ConstPool cp)
+ int index, String desc, ClassFile cf, ConstPool cp, ArrayList forwarders)
throws CannotCompileException
{
Class declClass = meth.getDeclaringClass();
@@ -964,7 +1010,7 @@ public class ProxyFactory {
MethodInfo forwarder
= makeForwarder(thisClassname, meth, desc, cp, declClass,
- delegatorName, index);
+ delegatorName, index, forwarders);
cf.addMethod(forwarder);
}
@@ -1154,7 +1200,8 @@ public class ProxyFactory {
*/
private static MethodInfo makeForwarder(String thisClassName,
Method meth, String desc, ConstPool cp,
- Class declClass, String delegatorName, int index) {
+ Class declClass, String delegatorName, int index,
+ ArrayList forwarders) {
MethodInfo forwarder = new MethodInfo(cp, meth.getName(), desc);
forwarder.setAccessFlags(Modifier.FINAL
| (meth.getModifiers() & ~(Modifier.ABSTRACT
@@ -1164,13 +1211,14 @@ public class ProxyFactory {
int args = Descriptor.paramSize(desc);
Bytecode code = new Bytecode(cp, 0, args + 2);
/*
- * if (methods[index * 2] == null) {
+ * static {
* methods[index * 2]
* = RuntimeSupport.findSuperMethod(this, <overridden name>, <desc>);
* methods[index * 2 + 1]
* = RuntimeSupport.findMethod(this, <delegator name>, <desc>);
* or = null // the original method is abstract.
* }
+ * :
* return ($r)handler.invoke(this, methods[index * 2],
* methods[index * 2 + 1], $args);
*/
@@ -1180,7 +1228,7 @@ public class ProxyFactory {
code.addGetstatic(thisClassName, HOLDER, HOLDER_TYPE);
code.addAstore(arrayVar);
- callFind2Methods(code, meth.getName(), delegatorName, origIndex, desc, arrayVar);
+ forwarders.add(new Find2MethodsArgs(meth.getName(), delegatorName, desc, origIndex));
code.addAload(0);
code.addGetfield(thisClassName, HANDLER, HANDLER_TYPE);
@@ -1207,6 +1255,18 @@ public class ProxyFactory {
return forwarder;
}
+ static class Find2MethodsArgs {
+ String methodName, delegatorName, descriptor;
+ int origIndex;
+
+ Find2MethodsArgs(String mname, String dname, String desc, int index) {
+ methodName = mname;
+ delegatorName = dname;
+ descriptor = desc;
+ origIndex = index;
+ }
+ }
+
private static void setThrows(MethodInfo minfo, ConstPool cp, Method orig) {
Class[] exceptions = orig.getExceptionTypes();
setThrows(minfo, cp, exceptions);
@@ -1313,28 +1373,6 @@ public class ProxyFactory {
return regno + FactoryHelper.dataSize[index];
}
- /**
- * @param thisMethod might be null.
- */
- private static void callFind2Methods(Bytecode code, String superMethod, String thisMethod,
- int index, String desc, int arrayVar) {
- String findClass = RuntimeSupport.class.getName();
- String findDesc
- = "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V";
-
- code.addAload(0);
- code.addLdc(superMethod);
- if (thisMethod == null)
- code.addOpcode(Opcode.ACONST_NULL);
- else
- code.addLdc(thisMethod);
-
- code.addIconst(index);
- code.addLdc(desc);
- code.addAload(arrayVar);
- code.addInvokestatic(findClass, "find2Methods", findDesc);
- }
-
private static void addUnwrapper(Bytecode code, Class type) {
if (type.isPrimitive()) {
if (type == Void.TYPE)
diff --git a/src/main/javassist/util/proxy/RuntimeSupport.java b/src/main/javassist/util/proxy/RuntimeSupport.java
index 48cacecd..4c5d8996 100644
--- a/src/main/javassist/util/proxy/RuntimeSupport.java
+++ b/src/main/javassist/util/proxy/RuntimeSupport.java
@@ -46,24 +46,13 @@ public class RuntimeSupport {
* @throws RuntimeException if the methods are not found.
* @see javassist.util.proxy.ProxyFactory
*/
- public static void find2Methods(Object self, String superMethod,
+ public static void find2Methods(Class clazz, String superMethod,
String thisMethod, int index,
String desc, java.lang.reflect.Method[] methods)
{
- /* Once methods[index] and methods[index + 1] are set to non-null,
- * then their values never change.
- */
- if (methods[index] == null || methods[index + 1] == null) {
- Method m1 = thisMethod == null ? null
- : findMethod(self, thisMethod, desc);
- Method m0 = findSuperMethod(self, superMethod, desc);
- synchronized (methods) {
- if (methods[index] == null) {
- methods[index + 1] = m1;
- methods[index] = m0;
- }
- }
- }
+ methods[index + 1] = thisMethod == null ? null
+ : findMethod(clazz, thisMethod, desc);
+ methods[index] = findSuperMethod(clazz, superMethod, desc);
}
/**
@@ -72,10 +61,10 @@ public class RuntimeSupport {
*
* @throws RuntimeException if the method is not found.
*/
- public static Method findMethod(Object self, String name, String desc) {
- Method m = findMethod2(self.getClass(), name, desc);
+ public static Method findMethod(Class clazz, String name, String desc) {
+ Method m = findMethod2(clazz, name, desc);
if (m == null)
- error(self, name, desc);
+ error(clazz, name, desc);
return m;
}
@@ -86,21 +75,20 @@ public class RuntimeSupport {
*
* @throws RuntimeException if the method is not found.
*/
- public static Method findSuperMethod(Object self, String name, String desc) {
- Class clazz = self.getClass();
+ public static Method findSuperMethod(Class clazz, String name, String desc) {
Method m = findSuperMethod2(clazz.getSuperclass(), name, desc);
if (m == null)
m = searchInterfaces(clazz, name, desc);
if (m == null)
- error(self, name, desc);
+ error(clazz, name, desc);
return m;
}
- private static void error(Object self, String name, String desc) {
+ private static void error(Class clazz, String name, String desc) {
throw new RuntimeException("not found " + name + ":" + desc
- + " in " + self.getClass().getName());
+ + " in " + clazz.getName());
}
private static Method findSuperMethod2(Class clazz, String name, String desc) {
diff --git a/src/test/javassist/JvstTest.java b/src/test/javassist/JvstTest.java
index 4e22dbc1..596d62e2 100644
--- a/src/test/javassist/JvstTest.java
+++ b/src/test/javassist/JvstTest.java
@@ -1116,14 +1116,14 @@ public class JvstTest extends JvstTestRoot {
suite.addTestSuite(javassist.bytecode.InsertGap0.class);
suite.addTestSuite(javassist.tools.reflect.LoaderTest.class);
suite.addTestSuite(testproxy.ProxyTester.class);
- // suite.addTestSuite(testproxy.ProxyFactoryPerformanceTest.class);
+ suite.addTestSuite(testproxy.ProxyFactoryPerformanceTest.class); // remove?
suite.addTestSuite(javassist.proxyfactory.ProxyFactoryTest.class);
suite.addTestSuite(javassist.proxyfactory.Tester.class);
suite.addTestSuite(test.javassist.proxy.ProxySerializationTest.class);
suite.addTestSuite(test.javassist.convert.ArrayAccessReplaceTest.class);
suite.addTestSuite(test.javassist.proxy.JASSIST113RegressionTest.class);
suite.addTestSuite(test.javassist.proxy.JBPAPP9257Test.class);
- //suite.addTestSuite(test.javassist.proxy.ProxyCacheGCTest.class);
+ suite.addTestSuite(test.javassist.proxy.ProxyCacheGCTest.class); // remvoe?
suite.addTestSuite(test.javassist.proxy.ProxyFactoryCompatibilityTest.class);
suite.addTestSuite(test.javassist.proxy.ProxySerializationTest.class);
suite.addTestSuite(test.javassist.proxy.ProxySimpleTest.class);
diff --git a/src/test/javassist/proxyfactory/ProxyFactoryTest.java b/src/test/javassist/proxyfactory/ProxyFactoryTest.java
index 7224eb50..232a0165 100644
--- a/src/test/javassist/proxyfactory/ProxyFactoryTest.java
+++ b/src/test/javassist/proxyfactory/ProxyFactoryTest.java
@@ -12,8 +12,6 @@ import java.lang.reflect.Method;
* <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
*/
public class ProxyFactoryTest extends TestCase {
-
-
public void testMethodHandlers() throws Exception {
ProxyFactory fact = new ProxyFactory();
fact.setSuperclass(MyCls.class);
diff --git a/src/test/test/javassist/proxy/ProxySimpleTest.java b/src/test/test/javassist/proxy/ProxySimpleTest.java
index f74fce45..cab62397 100644
--- a/src/test/test/javassist/proxy/ProxySimpleTest.java
+++ b/src/test/test/javassist/proxy/ProxySimpleTest.java
@@ -9,9 +9,47 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
+import javassist.util.proxy.MethodFilter;
+import javassist.util.proxy.MethodHandler;
+import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
public class ProxySimpleTest extends TestCase {
+
+ String testResult;
+
+ public void testProxyFactory() throws Exception {
+ ProxyFactory f = new ProxyFactory();
+ f.writeDirectory = "./proxy";
+ f.setSuperclass(Foo.class);
+ f.setFilter(new MethodFilter() {
+ public boolean isHandled(Method m) {
+ return m.getName().startsWith("f");
+ }
+ });
+ Class c = f.createClass();
+ MethodHandler mi = new MethodHandler() {
+ public Object invoke(Object self, Method m, Method proceed,
+ Object[] args) throws Throwable {
+ testResult += args[0].toString();
+ return proceed.invoke(self, args); // execute the original method.
+ }
+ };
+ Foo foo = (Foo)c.newInstance();
+ ((Proxy)foo).setHandler(mi);
+ testResult = "";
+ foo.foo(1);
+ foo.foo2(2);
+ foo.bar(3);
+ assertEquals("12", testResult);
+ }
+
+ public static class Foo {
+ public int foo(int i) { return i + 1; }
+ public int foo2(int i) { return i + 2; }
+ public int bar(int i) { return i + 1; }
+ }
+
public void testReadWrite() throws Exception {
final String fileName = "read-write.bin";
ProxyFactory.ClassLoaderProvider cp = ProxyFactory.classLoaderProvider;