转:动态代理方案性能对比
因服务框架需要用动态代理生成客户端接口的stub,所以做了一下性能评测,
动态代理工具比较成熟的产品有:
JDK自带的,ASM,CGLIB(基于ASM包装),JAVAASSIST,
使用的版本分别为:
JDK-1.6.0_18-b07, ASM-3.3, CGLIB-2.2, JAVAASSIST-3.11.0.GA
(一) 测试结果:
数据为执行三次,每次调用一千万次代理方法的结果,测试代码后面有贴出。
(1) PC机测试结果:Linux 2.6.9-42.ELsmp(32bit), 2 Cores CPU(Intel Pentium4 3.06GHz)
Create JDK Proxy: 13 ms
Create CGLIB Proxy: 217 ms
Create JAVAASSIST Proxy: 99 ms
Create JAVAASSIST Bytecode Proxy: 168 ms
Create ASM Proxy: 3 ms
================
Run JDK Proxy: 2224 ms, 634,022 t/s
Run CGLIB Proxy: 1123 ms, 1,255,623 t/s
Run JAVAASSIST Proxy: 3212 ms, 438,999 t/s
Run JAVAASSIST Bytecode Proxy: 206 ms, 6,844,977 t/s
Run ASM Bytecode Proxy: 209 ms, 6,746,724 t/s
—————-
Run JDK Proxy: 2169 ms, 650,099 t/s
Run CGLIB Proxy: 1059 ms, 1,331,506 t/s
Run JAVAASSIST Proxy: 3328 ms, 423,697 t/s
Run JAVAASSIST Bytecode Proxy: 202 ms, 6,980,521 t/s
Run ASM Bytecode Proxy: 206 ms, 6,844,977 t/s
—————-
Run JDK Proxy: 2174 ms, 648,604 t/s
Run CGLIB Proxy: 1032 ms, 1,366,342 t/s
Run JAVAASSIST Proxy: 3119 ms, 452,088 t/s
Run JAVAASSIST Bytecode Proxy: 207 ms, 6,811,910 t/s
Run ASM Bytecode Proxy: 207 ms, 6,811,910 t/s
—————-
(2) 服务器测试结果:Linux 2.6.18-128.el5xen(64bit), 16 Cores CPU(Intel Xeon E5520 2.27GHz)
Create JDK Proxy: 7 ms
Create CGLIB Proxy: 86 ms
Create JAVAASSIST Proxy: 36 ms
Create JAVAASSIST Bytecode Proxy: 57 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 235 ms, 6,000,278 t/s
Run CGLIB Proxy: 234 ms, 6,025,920 t/s
Run JAVAASSIST Proxy: 459 ms, 3,072,037 t/s
Run JAVAASSIST Bytecode Proxy: 71 ms, 19,860,076 t/s
Run ASM Bytecode Proxy: 72 ms, 19,584,241 t/s
—————-
Run JDK Proxy: 298 ms, 4,731,763 t/s
Run CGLIB Proxy: 134 ms, 10,522,876 t/s
Run JAVAASSIST Proxy: 406 ms, 3,473,067 t/s
Run JAVAASSIST Bytecode Proxy: 67 ms, 21,045,752 t/s
Run ASM Bytecode Proxy: 66 ms, 21,364,627 t/s
—————-
Run JDK Proxy: 282 ms, 5,000,231 t/s
Run CGLIB Proxy: 133 ms, 10,601,995 t/s
Run JAVAASSIST Proxy: 406 ms, 3,473,067 t/s
Run JAVAASSIST Bytecode Proxy: 67 ms, 21,045,752 t/s
Run ASM Bytecode Proxy: 67 ms, 21,045,752 t/s
—————-
(二) 测试结论:
1. ASM和JAVAASSIST字节码生成方式不相上下,都很快,是CGLIB的5倍。
2. CGLIB次之,是JDK自带的两倍。
3. JDK自带的再次之,因JDK1.6对动态代理做了优化,如果用低版本JDK更慢,要注意的是JDK也是通过字节码生成来实现动态代理的,而不是反射。
4. JAVAASSIST提供者动态代理接口最慢,比JDK自带的还慢。
(这也是为什么网上有人说JAVAASSIST比JDK还慢的原因,用JAVAASSIST最好别用它提供的动态代理接口,而可以考虑用它的字节码生成方式)
(三) 差异原因:
各方案生成的字节码不一样,
像JDK和CGLIB都考虑了很多因素,以及继承或包装了自己的一些类,
所以生成的字节码非常大,而我们很多时候用不上这些,
而手工生成的字节码非常小,所以速度快,
具体的字节码对比,后面有贴出,可自行分析。
(四) 最终选型:
最终决定使用JAVAASSIST的字节码生成代理方式,
虽然ASM稍快,但并没有快一个数量级,
而JAVAASSIST的字节码生成方式比ASM方便,
JAVAASSIST只需用字符串拼接出Java源码,便可生成相应字节码,
而ASM需要手工写字节码。
(五) 测试代码:
public interface CountService {
int count();
}
public class CountServiceImpl implements CountService {
private int count = 0;
public int count() {
return count ++;
}
}
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.DecimalFormat;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;public class DynamicProxyPerformanceTest {
public static void main(String[] args) throws Exception {
CountService delegate = new CountServiceImpl();long time = System.currentTimeMillis();
CountService jdkProxy = createJdkDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JDK Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService cglibProxy = createCglibDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create CGLIB Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService javassistProxy = createJavassistDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JAVAASSIST Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService javassistBytecodeProxy = createJavassistBytecodeDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create JAVAASSIST Bytecode Proxy: ” + time + ” ms”);time = System.currentTimeMillis();
CountService asmBytecodeProxy = createAsmBytecodeDynamicProxy(delegate);
time = System.currentTimeMillis() – time;
System.out.println(“Create ASM Proxy: ” + time + ” ms”);
System.out.println(“================”);for (int i = 0; i < 3; i++) {
test(jdkProxy, “Run JDK Proxy: “);
test(cglibProxy, “Run CGLIB Proxy: “);
test(javassistProxy, “Run JAVAASSIST Proxy: “);
test(javassistBytecodeProxy, “Run JAVAASSIST Bytecode Proxy: “);
test(asmBytecodeProxy, “Run ASM Bytecode Proxy: “);
System.out.println(“—————-”);
}
}private static void test(CountService service, String label)
throws Exception {
service.count(); // warm up
int count = 10000000;
long time = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
service.count();
}
time = System.currentTimeMillis() – time;
System.out.println(label + time + ” ms, ” + new DecimalFormat().format(count * 1000 / time) + ” t/s”);
}private static CountService createJdkDynamicProxy(final CountService delegate) {
CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[] { CountService.class }, new JdkHandler(delegate));
return jdkProxy;
}private static class JdkHandler implements InvocationHandler {
final Object delegate;
JdkHandler(Object delegate) {
this.delegate = delegate;
}public Object invoke(Object object, Method method, Object[] objects)
throws Throwable {
return method.invoke(delegate, objects);
}
}private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setCallback(new CglibInterceptor(delegate));
enhancer.setInterfaces(new Class[] { CountService.class });
CountService cglibProxy = (CountService) enhancer.create();
return cglibProxy;
}private static class CglibInterceptor implements MethodInterceptor {
final Object delegate;
CglibInterceptor(Object delegate) {
this.delegate = delegate;
}public Object intercept(Object object, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
return methodProxy.invoke(delegate, objects);
}
}private static CountService createJavassistDynamicProxy(final CountService delegate) throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(new Class[] { CountService.class });
Class<?> proxyClass = proxyFactory.createClass();
CountService javassistProxy = (CountService) proxyClass.newInstance();
((ProxyObject) javassistProxy).setHandler(new JavaAssitInterceptor(delegate));
return javassistProxy;
}private static class JavaAssitInterceptor implements MethodHandler {
final Object delegate;
JavaAssitInterceptor(Object delegate) {
this.delegate = delegate;
}public Object invoke(Object self, Method m, Method proceed,
Object[] args) throws Throwable {
return m.invoke(delegate, args);
}
}private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception {
ClassPool mPool = new ClassPool(true);
CtClass mCtc = mPool.makeClass(CountService.class.getName() + “JavaassistProxy”);
mCtc.addInterface(mPool.get(CountService.class.getName()));
mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
mCtc.addField(CtField.make(“public ” + CountService.class.getName() + ” delegate;”, mCtc));
mCtc.addMethod(CtNewMethod.make(“public int count() { return delegate.count(); }”, mCtc));
Class<?> pc = mCtc.toClass();
CountService bytecodeProxy = (CountService) pc.newInstance();
Field filed = bytecodeProxy.getClass().getField(“delegate”);
filed.set(bytecodeProxy, delegate);
return bytecodeProxy;
}private static CountService createAsmBytecodeDynamicProxy(CountService delegate) throws Exception {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
String className = CountService.class.getName() + “AsmProxy”;
String classPath = className.replace(‘.’, ‘/’);
String interfacePath = CountService.class.getName().replace(‘.’, ‘/’);
classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, classPath, null, “java/lang/Object”, new String[] {interfacePath});MethodVisitor initVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, “<init>”, “()V”, null, null);
initVisitor.visitCode();
initVisitor.visitVarInsn(Opcodes.ALOAD, 0);
initVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, “java/lang/Object”, “<init>”, “()V”);
initVisitor.visitInsn(Opcodes.RETURN);
initVisitor.visitMaxs(0, 0);
initVisitor.visitEnd();FieldVisitor fieldVisitor = classWriter.visitField(Opcodes.ACC_PUBLIC, “delegate”, “L” + interfacePath + “;”, null, null);
fieldVisitor.visitEnd();MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, “count”, “()I”, null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, classPath, “delegate”, “L” + interfacePath + “;”);
methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, interfacePath, “count”, “()I”);
methodVisitor.visitInsn(Opcodes.IRETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();classWriter.visitEnd();
byte[] code = classWriter.toByteArray();
CountService bytecodeProxy = (CountService) new ByteArrayClassLoader().getClass(className, code).newInstance();
Field filed = bytecodeProxy.getClass().getField(“delegate”);
filed.set(bytecodeProxy, delegate);
return bytecodeProxy;
}private static class ByteArrayClassLoader extends ClassLoader {
public ByteArrayClassLoader() {
super(ByteArrayClassLoader.class.getClassLoader());
}public synchronized Class<?> getClass(String name, byte[] code) {
if (name == null) {
throw new IllegalArgumentException(“”);
}
return defineClass(name, code, 0, code.length);
}}
}
(六) 字节码对比
(1) JDK生成的字节码:
public final class $Proxy0 extends java.lang.reflect.Proxy implements com.alibaba.test.performance.dynamicproxy.CountService{
public $Proxy0(java.lang.reflect.InvocationHandler) throws ;
Code:
0:aload_0
1:aload_1
2:invokespecial#8; //Method java/lang/reflect/Proxy.”":(Ljava/lang/reflect/InvocationHandler;)V
5:returnpublic final boolean equals(java.lang.Object) throws ;
Code:
0:aload_0
1:getfield#16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4:aload_0
5:getstatic#20; //Field m1:Ljava/lang/reflect/Method;
8:iconst_1
9:anewarray#22; //class java/lang/Object
12:dup
13:iconst_0
14:aload_1
15:aastore
16:invokeinterface#28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
21:checkcast#30; //class java/lang/Boolean
24:invokevirtual#34; //Method java/lang/Boolean.booleanValue:()Z
27:ireturn
28:athrow
29:astore_2
30:new#42; //class java/lang/reflect/UndeclaredThrowableException
33:dup
34:aload_2
35:invokespecial#45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
38:athrow
Exception table:
from to target type
0 28 28 Class java/lang/Error0 28 28 Class java/lang/RuntimeException
0 28 29 Class java/lang/Throwable
public final int count() throws ;
Code:
0:aload_0
1:getfield#16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4:aload_0
5:getstatic#50; //Field m3:Ljava/lang/reflect/Method;
8:aconst_null
9:invokeinterface#28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14:checkcast#52; //class java/lang/Integer
17:invokevirtual#55; //Method java/lang/Integer.intValue:()I
20:ireturn
21:athrow
22:astore_1
23:new#42; //class java/lang/reflect/UndeclaredThrowableException
26:dup
27:aload_1
28:invokespecial#45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
31:athrow
Exception table:
from to target type
0 21 21 Class java/lang/Error0 21 21 Class java/lang/RuntimeException
0 21 22 Class java/lang/Throwable
public final int hashCode() throws ;
Code:
0:aload_0
1:getfield#16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4:aload_0
5:getstatic#59; //Field m0:Ljava/lang/reflect/Method;
8:aconst_null
9:invokeinterface#28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14:checkcast#52; //class java/lang/Integer
17:invokevirtual#55; //Method java/lang/Integer.intValue:()I
20:ireturn
21:athrow
22:astore_1
23:new#42; //class java/lang/reflect/UndeclaredThrowableException
26:dup
27:aload_1
28:invokespecial#45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
31:athrow
Exception table:
from to target type
0 21 21 Class java/lang/Error0 21 21 Class java/lang/RuntimeException
0 21 22 Class java/lang/Throwable
public final java.lang.String toString() throws ;
Code:
0:aload_0
1:getfield#16; //Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4:aload_0
5:getstatic#64; //Field m2:Ljava/lang/reflect/Method;
8:aconst_null
9:invokeinterface#28, 4; //InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14:checkcast#66; //class java/lang/String
17:areturn
18:athrow
19:astore_1
20:new#42; //class java/lang/reflect/UndeclaredThrowableException
23:dup
24:aload_1
25:invokespecial#45; //Method java/lang/reflect/UndeclaredThrowableException."":(Ljava/lang/Throwable;)V
28:athrow
Exception table:
from to target type
0 18 18 Class java/lang/Error0 18 18 Class java/lang/RuntimeException
0 18 19 Class java/lang/Throwable
static {} throws ;
Code:
0:ldc#70; //String java.lang.Object
2:invokestatic#76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
5:ldc#77; //String equals
7:iconst_1
8:anewarray#72; //class java/lang/Class
11:dup
12:iconst_0
13:ldc#70; //String java.lang.Object
15:invokestatic#76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
18:aastore
19:invokevirtual#81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
22:putstatic#20; //Field m1:Ljava/lang/reflect/Method;
25:ldc#83; //String com.alibaba.test.performance.dynamicproxy.CountService
27:invokestatic#76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
30:ldc#84; //String count
32:iconst_0
33:anewarray#72; //class java/lang/Class
36:invokevirtual#81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
39:putstatic#50; //Field m3:Ljava/lang/reflect/Method;
42:ldc#70; //String java.lang.Object
44:invokestatic#76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
47:ldc#85; //String hashCode
49:iconst_0
50:anewarray#72; //class java/lang/Class
53:invokevirtual#81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
56:putstatic#59; //Field m0:Ljava/lang/reflect/Method;
59:ldc#70; //String java.lang.Object
61:invokestatic#76; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
64:ldc#86; //String toString
66:iconst_0
67:anewarray#72; //class java/lang/Class
70:invokevirtual#81; //Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
73:putstatic#64; //Field m2:Ljava/lang/reflect/Method;
76:return
77:astore_1
78:new#90; //class java/lang/NoSuchMethodError
81:dup
82:aload_1
83:invokevirtual#93; //Method java/lang/Throwable.getMessage:()Ljava/lang/String;
86:invokespecial#96; //Method java/lang/NoSuchMethodError."":(Ljava/lang/String;)V
89:athrow
90:astore_1
91:new#100; //class java/lang/NoClassDefFoundError
94:dup
95:aload_1
96:invokevirtual#93; //Method java/lang/Throwable.getMessage:()Ljava/lang/String;
99:invokespecial#101; //Method java/lang/NoClassDefFoundError."":(Ljava/lang/String;)V
102:athrow
Exception table:
from to target type
0 77 77 Class java/lang/NoSuchMethodException0 77 90 Class java/lang/ClassNotFoundException
}
(2) CGLIB生成的字节码:
public class net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7 extends net.sf.cglib.core.KeyFactory implements net.sf.cglib.core.MethodWrapper$MethodWrapperKey{
public net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7();
Code:
0:aload_0
1:invokespecial#11; //Method net/sf/cglib/core/KeyFactory."":()V
4:returnpublic java.lang.Object newInstance(java.lang.String, java.lang.String[], java.lang.String);
Code:
0:new#2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
3:dup
4:aload_1
5:aload_2
6:aload_3
7:invokespecial#16; //Method “”:(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
10:areturnpublic net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(java.lang.String, java.lang.String[], java.lang.String);
Code:
0:aload_0
1:invokespecial#11; //Method net/sf/cglib/core/KeyFactory.”":()V
4:aload_0
5:dup
6:aload_1
7:putfield#20; //Field FIELD_0:Ljava/lang/String;
10:dup
11:aload_2
12:putfield#24; //Field FIELD_1:[Ljava/lang/String;
15:dup
16:aload_3
17:putfield#27; //Field FIELD_2:Ljava/lang/String;
20:returnpublic int hashCode();
Code:
0:ldc#30; //int 938313161
2:aload_0
3:getfield#20; //Field FIELD_0:Ljava/lang/String;
6:swap
7:ldc#31; //int 362693231
9:imul
10:swap
11:dup
12:ifnull21
15:invokevirtual#35; //Method java/lang/Object.hashCode:()I
18:goto23
21:pop
22:iconst_0
23:iadd
24:aload_0
25:getfield#24; //Field FIELD_1:[Ljava/lang/String;
28:dup
29:ifnull71
32:astore_1
33:iconst_0
34:istore_2
35:goto62
38:aload_1
39:iload_2
40:aaload
41:swap
42:ldc#31; //int 362693231
44:imul
45:swap
46:dup
47:ifnull56
50:invokevirtual#35; //Method java/lang/Object.hashCode:()I
53:goto58
56:pop
57:iconst_0
58:iadd
59:iinc2, 1
62:iload_2
63:aload_1
64:arraylength
65:if_icmplt38
68:goto72
71:pop
72:aload_0
73:getfield#27; //Field FIELD_2:Ljava/lang/String;
76:swap
77:ldc#31; //int 362693231
79:imul
80:swap
81:dup
82:ifnull91
85:invokevirtual#35; //Method java/lang/Object.hashCode:()I
88:goto93
91:pop
92:iconst_0
93:iadd
94:ireturnpublic boolean equals(java.lang.Object);
Code:
0:aload_1
1:instanceof#2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
4:ifeq181
7:aload_0
8:getfield#20; //Field FIELD_0:Ljava/lang/String;
11:aload_1
12:checkcast#2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
15:getfield#20; //Field FIELD_0:Ljava/lang/String;
18:dup2
19:ifnonnull29
22:ifnonnull35
25:pop2
26:goto45
29:ifnull35
32:goto39
35:pop2
36:goto181
39:invokevirtual#39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
42:ifeq181
45:aload_0
46:getfield#24; //Field FIELD_1:[Ljava/lang/String;
49:aload_1
50:checkcast#2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
53:getfield#24; //Field FIELD_1:[Ljava/lang/String;
56:dup2
57:ifnonnull67
60:ifnonnull73
63:pop2
64:goto141
67:ifnull73
70:goto77
73:pop2
74:goto181
77:dup2
78:arraylength
79:swap
80:arraylength
81:if_icmpeq88
84:pop2
85:goto181
88:astore_2
89:astore_3
90:iconst_0
91:istore4
93:goto134
96:aload_2
97:iload4
99:aaload
100:aload_3
101:iload4
103:aaload
104:dup2
105:ifnonnull115
108:ifnonnull121
111:pop2
112:goto131
115:ifnull121
118:goto125
121:pop2
122:goto181
125:invokevirtual#39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
128:ifeq181
131:iinc4, 1
134:iload4
136:aload_2
137:arraylength
138:if_icmplt96
141:aload_0
142:getfield#27; //Field FIELD_2:Ljava/lang/String;
145:aload_1
146:checkcast#2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
149:getfield#27; //Field FIELD_2:Ljava/lang/String;
152:dup2
153:ifnonnull163
156:ifnonnull169
159:pop2
160:goto179
163:ifnull169
166:goto173
169:pop2
170:goto181
173:invokevirtual#39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
176:ifeq181
179:iconst_1
180:ireturn
181:iconst_0
182:ireturnpublic java.lang.String toString();
Code:
0:new#43; //class java/lang/StringBuffer
3:dup
4:invokespecial#44; //Method java/lang/StringBuffer.”":()V
7:aload_0
8:getfield#20; //Field FIELD_0:Ljava/lang/String;
11:dup
12:ifnull24
15:invokevirtual#46; //Method java/lang/Object.toString:()Ljava/lang/String;
18:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
21:goto30
24:pop
25:ldc#52; //String null
27:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
30:ldc#54; //String ,
32:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
35:aload_0
36:getfield#24; //Field FIELD_1:[Ljava/lang/String;
39:dup
40:ifnull110
43:swap
44:ldc#56; //String {
46:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
49:swap
50:astore_1
51:iconst_0
52:istore_2
53:goto86
56:aload_1
57:iload_2
58:aaload
59:dup
60:ifnull72
63:invokevirtual#46; //Method java/lang/Object.toString:()Ljava/lang/String;
66:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
69:goto78
72:pop
73:ldc#52; //String null
75:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
78:ldc#54; //String ,
80:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
83:iinc2, 1
86:iload_2
87:aload_1
88:arraylength
89:if_icmplt56
92:dup
93:dup
94:invokevirtual#59; //Method java/lang/StringBuffer.length:()I
97:iconst_2
98:isub
99:invokevirtual#63; //Method java/lang/StringBuffer.setLength:(I)V
102:ldc#65; //String }
104:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
107:goto116
110:pop
111:ldc#52; //String null
113:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
116:ldc#54; //String ,
118:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
121:aload_0
122:getfield#27; //Field FIELD_2:Ljava/lang/String;
125:dup
126:ifnull138
129:invokevirtual#46; //Method java/lang/Object.toString:()Ljava/lang/String;
132:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
135:goto144
138:pop
139:ldc#52; //String null
141:invokevirtual#50; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
144:invokevirtual#66; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
147:areturn}
(3) JAVAASSIST动态代理接口生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountService_$$_javassist_0 extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService,javassist.util.proxy.ProxyObject{
public static javassist.util.proxy.MethodHandler default_interceptor;public static javassist.util.proxy.MethodFilter _method_filter;
public com.alibaba.test.performance.dynamicproxy.CountService_$$_javassist_0();
Code:
0:aload_0
1:getstatic#19; //Field default_interceptor:Ljavassist/util/proxy/MethodHandler;
4:putfield#21; //Field handler:Ljavassist/util/proxy/MethodHandler;
7:getstatic#23; //Field default_interceptor:Ljavassist/util/proxy/MethodHandler;
10:ifnonnull20
13:aload_0
14:getstatic#27; //Field javassist/util/proxy/RuntimeSupport.default_interceptor:Ljavassist/util/proxy/MethodHandler;
17:putfield#29; //Field handler:Ljavassist/util/proxy/MethodHandler;
20:aload_0
21:invokespecial#31; //Method java/lang/Object.”":()V
24:returnpublic final boolean _d0equals(java.lang.Object);
Code:
0:aload_0
1:aload_1
2:invokespecial#38; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
5:ireturnpublic final boolean equals(java.lang.Object);
Code:
0:getstatic#42; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_2
4:aload_0
5:ldc#43; //String equals
7:ldc#44; //String _d0equals
9:iconst_0
10:ldc#45; //String (Ljava/lang/Object;)Z
12:aload_2
13:invokestatic#49; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16:aload_0
17:getfield#51; //Field handler:Ljavassist/util/proxy/MethodHandler;
20:aload_0
21:aload_2
22:iconst_0
23:aaload
24:aload_2
25:iconst_1
26:aaload
27:iconst_1
28:anewarray#52; //class java/lang/Object
31:dup
32:iconst_0
33:aload_1
34:aastore
35:invokeinterface#58, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
40:checkcast#60; //class java/lang/Boolean
43:invokevirtual#64; //Method java/lang/Boolean.booleanValue:()Z
46:ireturnpublic final java.lang.Object _d1clone() throws java.lang.CloneNotSupportedException;
Code:
0:aload_0
1:invokespecial#72; //Method java/lang/Object.clone:()Ljava/lang/Object;
4:areturnprotected final java.lang.Object clone() throws java.lang.CloneNotSupportedException;
Code:
0:getstatic#74; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_1
4:aload_0
5:ldc#75; //String clone
7:ldc#76; //String _d1clone
9:iconst_2
10:ldc#77; //String ()Ljava/lang/Object;
12:aload_1
13:invokestatic#79; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16:aload_0
17:getfield#81; //Field handler:Ljavassist/util/proxy/MethodHandler;
20:aload_0
21:aload_1
22:iconst_2
23:aaload
24:aload_1
25:iconst_3
26:aaload
27:iconst_0
28:anewarray#52; //class java/lang/Object
31:invokeinterface#83, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
36:checkcast#4; //class java/lang/Object
39:areturnpublic final int _d2hashCode();
Code:
0:aload_0
1:invokespecial#88; //Method java/lang/Object.hashCode:()I
4:ireturnpublic final int hashCode();
Code:
0:getstatic#90; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_1
4:aload_0
5:ldc#91; //String hashCode
7:ldc#92; //String _d2hashCode
9:iconst_4
10:ldc#93; //String ()I
12:aload_1
13:invokestatic#95; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16:aload_0
17:getfield#97; //Field handler:Ljavassist/util/proxy/MethodHandler;
20:aload_0
21:aload_1
22:iconst_4
23:aaload
24:aload_1
25:iconst_5
26:aaload
27:iconst_0
28:anewarray#52; //class java/lang/Object
31:invokeinterface#99, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
36:checkcast#101; //class java/lang/Integer
39:invokevirtual#104; //Method java/lang/Integer.intValue:()I
42:ireturnpublic final int count();
Code:
0:getstatic#107; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_1
4:aload_0
5:ldc#108; //String count
7:aconst_null
8:bipush6
10:ldc#109; //String ()I
12:aload_1
13:invokestatic#111; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
16:aload_0
17:getfield#113; //Field handler:Ljavassist/util/proxy/MethodHandler;
20:aload_0
21:aload_1
22:bipush6
24:aaload
25:aload_1
26:bipush7
28:aaload
29:iconst_0
30:anewarray#52; //class java/lang/Object
33:invokeinterface#115, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
38:checkcast#101; //class java/lang/Integer
41:invokevirtual#117; //Method java/lang/Integer.intValue:()I
44:ireturnpublic final void _d4finalize() throws java.lang.Throwable;
Code:
0:aload_0
1:invokespecial#123; //Method java/lang/Object.finalize:()V
4:returnprotected final void finalize() throws java.lang.Throwable;
Code:
0:getstatic#125; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_1
4:aload_0
5:ldc#126; //String finalize
7:ldc#127; //String _d4finalize
9:bipush8
11:ldc#128; //String ()V
13:aload_1
14:invokestatic#130; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
17:aload_0
18:getfield#132; //Field handler:Ljavassist/util/proxy/MethodHandler;
21:aload_0
22:aload_1
23:bipush8
25:aaload
26:aload_1
27:bipush9
29:aaload
30:iconst_0
31:anewarray#52; //class java/lang/Object
34:invokeinterface#134, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
39:pop
40:returnpublic final java.lang.String _d5toString();
Code:
0:aload_0
1:invokespecial#139; //Method java/lang/Object.toString:()Ljava/lang/String;
4:areturnpublic final java.lang.String toString();
Code:
0:getstatic#141; //Field _methods_:[Ljava/lang/reflect/Method;
3:astore_1
4:aload_0
5:ldc#142; //String toString
7:ldc#143; //String _d5toString
9:bipush10
11:ldc#144; //String ()Ljava/lang/String;
13:aload_1
14:invokestatic#146; //Method javassist/util/proxy/RuntimeSupport.find2Methods:(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/reflect/Method;)V
17:aload_0
18:getfield#148; //Field handler:Ljavassist/util/proxy/MethodHandler;
21:aload_0
22:aload_1
23:bipush10
25:aaload
26:aload_1
27:bipush11
29:aaload
30:iconst_0
31:anewarray#52; //class java/lang/Object
34:invokeinterface#150, 5; //InterfaceMethod javassist/util/proxy/MethodHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
39:checkcast#152; //class java/lang/String
42:areturnstatic {};
Code:
0:bipush12
2:anewarray#155; //class java/lang/reflect/Method
5:putstatic#157; //Field _methods_:[Ljava/lang/reflect/Method;
8:returnpublic void setHandler(javassist.util.proxy.MethodHandler);
Code:
0:aload_0
1:aload_1
2:putfield#161; //Field handler:Ljavassist/util/proxy/MethodHandler;
5:returnjava.lang.Object writeReplace() throws java.io.ObjectStreamException;
Code:
0:aload_0
1:invokestatic#168; //Method javassist/util/proxy/RuntimeSupport.makeSerializedProxy:(Ljava/lang/Object;)Ljavassist/util/proxy/SerializedProxy;
4:areturn}
(5) JAVAASSIST拼接源码生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountServiceJavaassistProxy extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService{
public com.alibaba.test.performance.dynamicproxy.CountService delegate;public com.alibaba.test.performance.dynamicproxy.CountServiceJavaassistProxy();
Code:
0:aload_0
1:invokespecial#12; //Method java/lang/Object.”":()V
4:returnpublic int count();
Code:
0:aload_0
1:getfield#19; //Field delegate:Lcom/alibaba/test/performance/dynamicproxy/CountService;
4:invokeinterface#21, 1; //InterfaceMethod com/alibaba/test/performance/dynamicproxy/CountService.count:()I
9:ireturn}
(6) 用ASM自行生成的字节码:
public class com.alibaba.test.performance.dynamicproxy.CountServiceAsmProxy extends java.lang.Object implements com.alibaba.test.performance.dynamicproxy.CountService{
public com.alibaba.test.performance.dynamicproxy.CountService delegate;public com.alibaba.test.performance.dynamicproxy.CountServiceAsmProxy();
Code:
0:aload_0
1:invokespecial#10; //Method java/lang/Object.”":()V
4:returnpublic int count();
Code:
0:aload_0
1:getfield#16; //Field delegate:Lcom/alibaba/test/performance/dynamicproxy/CountService;
4:invokeinterface#18, 1; //InterfaceMethod com/alibaba/test/performance/dynamicproxy/CountService.count:()I
9:ireturn}