动态代理方案性能对比 (CGLIB,ASSIT,JDK)
动态代理工具比较成熟的产品有:
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)
Java代码
- 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)
Java代码
- 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需要手工写字节码。
(五) 测试代码:
Java代码
public interface CountService {
int count();
}
Java代码
public class CountServiceImpl implements CountService { private int count = 0; public int count() {
return count++;
}
}
Java代码
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生成的字节码:
Java代码
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: return
public 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/Error
0 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/Error
0 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/Error
0 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/Error
0 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/NoSuchMethodException
0 77 90 Class java/lang/ClassNotFoundException
}
(2) CGLIB生成的字节码:
Java代码
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: return
public 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: areturn
public 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: return
public 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: ifnull 21
15: invokevirtual #35; //Method java/lang/Object.hashCode:()I
18: goto 23
21: pop
22: iconst_0
23: iadd
24: aload_0
25: getfield #24; //Field FIELD_1:[Ljava/lang/String;
28: dup
29: ifnull 71
32: astore_1
33: iconst_0
34: istore_2
35: goto 62
38: aload_1
39: iload_2
40: aaload
41: swap
42: ldc #31; //int 362693231
44: imul
45: swap
46: dup
47: ifnull 56
50: invokevirtual #35; //Method java/lang/Object.hashCode:()I
53: goto 58
56: pop
57: iconst_0
58: iadd
59: iinc 2, 1
62: iload_2
63: aload_1
64: arraylength
65: if_icmplt 38
68: goto 72
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: ifnull 91
85: invokevirtual #35; //Method java/lang/Object.hashCode:()I
88: goto 93
91: pop
92: iconst_0
93: iadd
94: ireturn
public boolean equals(java.lang.Object);
Code:
0: aload_1
1: instanceof #2; //class net/sf/cglib/core/MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7
4: ifeq 181
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: ifnonnull 29
22: ifnonnull 35
25: pop2
26: goto 45
29: ifnull 35
32: goto 39
35: pop2
36: goto 181
39: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
42: ifeq 181
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: ifnonnull 67
60: ifnonnull 73
63: pop2
64: goto 141
67: ifnull 73
70: goto 77
73: pop2
74: goto 181
77: dup2
78: arraylength
79: swap
80: arraylength
81: if_icmpeq 88
84: pop2
85: goto 181
88: astore_2
89: astore_3
90: iconst_0
91: istore 4
93: goto 134
96: aload_2
97: iload 4
99: aaload
100: aload_3
101: iload 4
103: aaload
104: dup2
105: ifnonnull 115
108: ifnonnull 121
111: pop2
112: goto 131
115: ifnull 121
118: goto 125
121: pop2
122: goto 181
125: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
128: ifeq 181
131: iinc 4, 1
134: iload 4
136: aload_2
137: arraylength
138: if_icmplt 96
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: ifnonnull 163
156: ifnonnull 169
159: pop2
160: goto 179
163: ifnull 169
166: goto 173
169: pop2
170: goto 181
173: invokevirtual #39; //Method java/lang/Object.equals:(Ljava/lang/Object;)Z
176: ifeq 181
179: iconst_1
180: ireturn
181: iconst_0
182: ireturn
public 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: ifnull 24
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: goto 30
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: ifnull 110
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: goto 86
56: aload_1
57: iload_2
58: aaload
59: dup
60: ifnull 72
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: goto 78
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: iinc 2, 1
86: iload_2
87: aload_1
88: arraylength
89: if_icmplt 56
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: goto 116
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: ifnull 138
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: goto 144
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动态代理接口生成的字节码:
Java代码
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: ifnonnull 20
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: return
public 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: ireturn
public 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: ireturn
public 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: areturn
protected 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: areturn
public final int _d2hashCode();
Code:
0: aload_0
1: invokespecial #88; //Method java/lang/Object.hashCode:()I
4: ireturn
public 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: ireturn
public 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: bipush 6
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: bipush 6
24: aaload
25: aload_1
26: bipush 7
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: ireturn
public final void _d4finalize() throws java.lang.Throwable;
Code:
0: aload_0
1: invokespecial #123; //Method java/lang/Object.finalize:()V
4: return
protected 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: bipush 8
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: bipush 8
25: aaload
26: aload_1
27: bipush 9
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: return
public final java.lang.String _d5toString();
Code:
0: aload_0
1: invokespecial #139; //Method java/lang/Object.toString:()Ljava/lang/String;
4: areturn
public 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: bipush 10
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: bipush 10
25: aaload
26: aload_1
27: bipush 11
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: areturn
static {};
Code:
0: bipush 12
2: anewarray #155; //class java/lang/reflect/Method
5: putstatic #157; //Field _methods_:[Ljava/lang/reflect/Method;
8: return
public void setHandler(javassist.util.proxy.MethodHandler);
Code:
0: aload_0
1: aload_1
2: putfield #161; //Field handler:Ljavassist/util/proxy/MethodHandler;
5: return
java.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拼接源码生成的字节码:
Java代码
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: return
public 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自行生成的字节码:
Java代码
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: return
public 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
}
动态代理方案性能对比 (CGLIB,ASSIT,JDK)的更多相关文章
- 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)
代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...
- Spring事务Transactional和动态代理(二)-cglib动态代理
系列文章索引: Spring事务Transactional和动态代理(一)-JDK代理实现 Spring事务Transactional和动态代理(二)-cglib动态代理 Spring事务Transa ...
- Adroid动态加载Apk-插件化技术框架(动态代理方案)
技术:Android + java +动态加载+插件化 概述 为什么要使用插件化?在开发中,一个项目只会越做越大.初始版本可能是单一功能,后续可能加上各种风马牛不相及的功能.所以我认为插件化可以使 ...
- JVM插码之四:Java动态代理机制的对比(JDK 和CGLIB,Javassist,ASM)
一.class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件, ...
- 动态代理(二)—— CGLIB代理原理
前篇文章动态代理(一)--JDK中的动态代理中详细介绍了JDK动态代理的Demo实现,api介绍,原理详解.这篇文章继续讨论Java中的动态代理,并提及了Java中动态代理的几种实现方式.这里继续介绍 ...
- Java动态代理(二)CGLIB动态代理应用
JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 .如果想代理没有实现接口的类可以使用CGLIB包. CGLI ...
- 面试官:你说你懂动态代理,那你知道为什么JDK中的代理类都要继承Proxy吗?
之前我已经写过了关于动态代理的两篇文章,本来以为这块应该没啥问题,没想到今天又被难住了- 太难了!!! 之前文章的链接: 动态代理学习(一)自己动手模拟JDK动态代理. 动态代理学习(二)JDK动态代 ...
- Java动态代理(三)——Cglib动态代理
一.Cglib动态代理Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能.而且,它的运行速度要远远快 ...
- java面试题之spring aop中jdk和cglib哪个动态代理的性能更好?
在jdk6和jdk7的时候,jdk比cglib要慢: 在jdk8的时候,jdk性能得到提升比cglib要快很多: 结论出自:https://www.cnblogs.com/xuliugen/p/104 ...
随机推荐
- manjaro i3 配置笔记
更改国内源 sudo pacman-mirrors -GB testing -c China 增加Arch linuxcn源 在/etc/pacman.conf文件末尾添加两行: [archlinux ...
- unity3d 移动与旋转 1
移动与旋转 1 player角色随asdw按键左右上下移动并旋转 public void Update() { // Reset player rotation to look in the same ...
- 和大于S的最小子数组 · Minimum Size Subarray Sum
[抄题]: 给定一个由 n 个正整数组成的数组和一个正整数 s ,请找出该数组中满足其和 ≥ s 的最小长度子数组.如果无解,则返回 -1. 给定数组 [2,3,1,2,4,3] 和 s = 7, 子 ...
- python全栈考试
1.执行 Python 脚本的两种方式 shell直接调用python脚本 python run.py 调用解释器来调用脚本 2.2.简述位.字节的关系 每8个位bit,组成一个字节byte. 一个 ...
- Laravel 多态关联使用的案例
1.实现的功能,:短信发送,需要签名和模板审核,审核结果要插进审核记录表 2,在signature(签名表模型)和 template(模板表模型)添加多态对应关系代码其实一样,代码如下: 审核记录表需 ...
- 01 Flume系列(一)安装配置
01 Flume系列(一)安装配置 Flume(http://flume.apache.org/) is a distributed, reliable, and available service ...
- asp.net 4高级程序设计( 第4版)文摘
第一部分 核心概念 第1章 asp.net 简介 第2章 visual studio 第3章 Web窗体 3.2 web窗体处理阶段 页面框架初始化(page.init),用户代码初始化(page.l ...
- java中double和float精度丢失问题
为什么会出现这个问题呢,就这是java和其它计算机语言都会出现的问题,下面我们分析一下为什么会出现这个问题:float和double类型主要是为了科学计算和工程计算而设计的.他们执行二进制浮点运算,这 ...
- 三种调用WCF服务的代码
wsHttpBinding,Massage UserName认证 static void Main(string[] args) { //使用服务引用方式生成的Client调用服务,使用自动生成的配置 ...
- 2016-2017 《移动平台开发》实验三 敏捷开发与XP实践
概述 软件=程序+软件工程 软件企业=软件+商业模式 XP是一种轻量(敏捷).高效.低风险.柔性.可预测.科学而且充满乐趣的软件开发方式. 在更短的周期内,更早地提供具体.持续的反馈信息. 在迭代的进 ...