http://pt.alibaba-inc.com/wp/experience_1054/dynamic_proxy_performance.html
因服务框架需要用动态代理生成客户端接口的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: 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生成的字节码:
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动态代理接口生成的字节码:
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拼接源码生成的字节码:
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自行生成的字节码:
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 }