- 浏览: 1677662 次
- 性别:
- 来自: 杭州699号
文章分类
最新评论
-
莫莫摸:
为什么不用dubbo
RCP数据传输模型回顾 -
大胡子爸爸:
String, Class 都实现了Serializable接 ...
RPC框架几行代码就够了 -
lss598018587:
谢谢大神分享,比起新手看复杂的dubbo框架还不如看大神的这一 ...
RPC框架几行代码就够了 -
15606915740:
你好,请问一下。<dubbo:consumer filt ...
Dubbo文档 -
joqk12345:
...
一些设计上的基本常识
转于自己在公司的Blog:
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)
(2) 服务器测试结果:Linux 2.6.18-128.el5xen(64bit), 16 Cores CPU(Intel Xeon E5520 2.27GHz)
(二) 测试结论:
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需要手工写字节码。
(五) 测试代码:
(六) 字节码对比
(1) JDK生成的字节码:
(2) CGLIB生成的字节码:
(3) JAVAASSIST动态代理接口生成的字节码:
(5) JAVAASSIST拼接源码生成的字节码:
(6) 用ASM自行生成的字节码:
Gavin King也是RedHat旗下的,当然选同宗的了,呵呵。
可以用:
javap -c 类名
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 }
评论
13 楼
skzr.org
2017-07-30
如果要用可以参考如下
我的测试结果:神舟K590s Core i7-3630QM四核, 24G DDR3,
jvm: jdk1.8, -client -Xms2g -Xmx2g
- Spring体系,建议采用spring-aop cglib实现
- Javassist(bytecode):性能和ASM差不多,但是比ASM容易编写
我的测试结果:神舟K590s Core i7-3630QM四核, 24G DDR3,
jvm: jdk1.8, -client -Xms2g -Xmx2g
Run NO Proxy: 37 ms, 38,109,875 t/s Run JDK Proxy: 85 ms, 16,589,004 t/s Run CGLIB Proxy: 52 ms, 27,116,642 t/s Run Spring interface Proxy: 205 ms, 6,878,367 t/s Run Spring class Proxy: 38 ms, 37,106,984 t/s Run JAVAASSIST Proxy: 108 ms, 13,056,161 t/s Run JAVAASSIST Bytecode Proxy: 39 ms, 36,155,523 t/s Run ASM Bytecode Proxy: 39 ms, 36,155,523 t/s
xiaoxr 写道
测试机器:ryzen7 1700, 16G DDR4 2400运行用例的结果:
Create JDK Proxy: 5 ms
Create CGLIB Proxy: 82 ms
Create JAVAASSIST Proxy: 32 ms
Create JAVAASSIST Bytecode Proxy: 45 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 41 ms, 34,391,839 t/s
Run CGLIB Proxy: 57 ms, 24,737,989 t/s
Run JAVAASSIST Proxy: 265 ms, 5,321,001 t/s
Run JAVAASSIST Bytecode Proxy: 56 ms, 25,179,739 t/s
Run ASM Bytecode Proxy: 52 ms, 27,116,642 t/s
----------------
Run JDK Proxy: 73 ms, 19,315,964 t/s
Run CGLIB Proxy: 23 ms, 61,307,191 t/s
Run JAVAASSIST Proxy: 223 ms, 6,323,163 t/s
Run JAVAASSIST Bytecode Proxy: 45 ms, 31,334,786 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
Run JDK Proxy: 62 ms, 22,742,990 t/s
Run CGLIB Proxy: 51 ms, 27,648,341 t/s
Run JAVAASSIST Proxy: 264 ms, 5,341,156 t/s
Run JAVAASSIST Bytecode Proxy: 46 ms, 30,653,595 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
版本:jdk:1.8.0_131, cglib:3.2.4, javassist:3.12.1GA, ASM: 5.1
结论:JDK和cglib的效率与ASM已经不再是数量级的差距,尤其是jdk8进步非常大 ,javassist代理依然是最慢的,从易用性角度还是选择jdk和cglib更好。
Create JDK Proxy: 5 ms
Create CGLIB Proxy: 82 ms
Create JAVAASSIST Proxy: 32 ms
Create JAVAASSIST Bytecode Proxy: 45 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 41 ms, 34,391,839 t/s
Run CGLIB Proxy: 57 ms, 24,737,989 t/s
Run JAVAASSIST Proxy: 265 ms, 5,321,001 t/s
Run JAVAASSIST Bytecode Proxy: 56 ms, 25,179,739 t/s
Run ASM Bytecode Proxy: 52 ms, 27,116,642 t/s
----------------
Run JDK Proxy: 73 ms, 19,315,964 t/s
Run CGLIB Proxy: 23 ms, 61,307,191 t/s
Run JAVAASSIST Proxy: 223 ms, 6,323,163 t/s
Run JAVAASSIST Bytecode Proxy: 45 ms, 31,334,786 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
Run JDK Proxy: 62 ms, 22,742,990 t/s
Run CGLIB Proxy: 51 ms, 27,648,341 t/s
Run JAVAASSIST Proxy: 264 ms, 5,341,156 t/s
Run JAVAASSIST Bytecode Proxy: 46 ms, 30,653,595 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
版本:jdk:1.8.0_131, cglib:3.2.4, javassist:3.12.1GA, ASM: 5.1
结论:JDK和cglib的效率与ASM已经不再是数量级的差距,尤其是jdk8进步非常大 ,javassist代理依然是最慢的,从易用性角度还是选择jdk和cglib更好。
12 楼
xiaoxr
2017-06-18
测试机器:ryzen7 1700, 16G DDR4 2400运行用例的结果:
Create JDK Proxy: 5 ms
Create CGLIB Proxy: 82 ms
Create JAVAASSIST Proxy: 32 ms
Create JAVAASSIST Bytecode Proxy: 45 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 41 ms, 34,391,839 t/s
Run CGLIB Proxy: 57 ms, 24,737,989 t/s
Run JAVAASSIST Proxy: 265 ms, 5,321,001 t/s
Run JAVAASSIST Bytecode Proxy: 56 ms, 25,179,739 t/s
Run ASM Bytecode Proxy: 52 ms, 27,116,642 t/s
----------------
Run JDK Proxy: 73 ms, 19,315,964 t/s
Run CGLIB Proxy: 23 ms, 61,307,191 t/s
Run JAVAASSIST Proxy: 223 ms, 6,323,163 t/s
Run JAVAASSIST Bytecode Proxy: 45 ms, 31,334,786 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
Run JDK Proxy: 62 ms, 22,742,990 t/s
Run CGLIB Proxy: 51 ms, 27,648,341 t/s
Run JAVAASSIST Proxy: 264 ms, 5,341,156 t/s
Run JAVAASSIST Bytecode Proxy: 46 ms, 30,653,595 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
版本:jdk:1.8.0_131, cglib:3.2.4, javassist:3.12.1GA, ASM: 5.1
结论:JDK和cglib的效率与ASM已经不再是数量级的差距,尤其是jdk8进步非常大 ,javassist代理依然是最慢的,从易用性角度还是选择jdk和cglib更好。
Create JDK Proxy: 5 ms
Create CGLIB Proxy: 82 ms
Create JAVAASSIST Proxy: 32 ms
Create JAVAASSIST Bytecode Proxy: 45 ms
Create ASM Proxy: 1 ms
================
Run JDK Proxy: 41 ms, 34,391,839 t/s
Run CGLIB Proxy: 57 ms, 24,737,989 t/s
Run JAVAASSIST Proxy: 265 ms, 5,321,001 t/s
Run JAVAASSIST Bytecode Proxy: 56 ms, 25,179,739 t/s
Run ASM Bytecode Proxy: 52 ms, 27,116,642 t/s
----------------
Run JDK Proxy: 73 ms, 19,315,964 t/s
Run CGLIB Proxy: 23 ms, 61,307,191 t/s
Run JAVAASSIST Proxy: 223 ms, 6,323,163 t/s
Run JAVAASSIST Bytecode Proxy: 45 ms, 31,334,786 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
Run JDK Proxy: 62 ms, 22,742,990 t/s
Run CGLIB Proxy: 51 ms, 27,648,341 t/s
Run JAVAASSIST Proxy: 264 ms, 5,341,156 t/s
Run JAVAASSIST Bytecode Proxy: 46 ms, 30,653,595 t/s
Run ASM Bytecode Proxy: 46 ms, 30,653,595 t/s
----------------
版本:jdk:1.8.0_131, cglib:3.2.4, javassist:3.12.1GA, ASM: 5.1
结论:JDK和cglib的效率与ASM已经不再是数量级的差距,尤其是jdk8进步非常大 ,javassist代理依然是最慢的,从易用性角度还是选择jdk和cglib更好。
11 楼
lovearpu
2016-11-25
[color=gray][b]
[/b][/color]
[flash=200,200][url][img][list] |
[*]
|
[/list][/img][/url][/flash] |
" target="_blank">" />" target="_blank">" wmode="" quality="high" menu="false" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="200" height="200"> |
10 楼
wynlqxm
2016-08-19
哥,我看你贴出的【JDK生成的字节码】看到的都是/Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class等等反射相关的api。为什么您还是觉得“要注意的是JDK也是通过字节码生成来实现动态代理的,而不是反射”,可否解释下。谢谢。打扰了。
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;
9 楼
北冥郎
2014-12-15
楼主所说JDK也是通过字节码生成来实现动态代理的,而不是反射。这个不太理解,JdkHandler中的 return method.invoke(delegate, objects); 这就用到了反射啊。
另外一个问题,cglib和javassit动态生成字节码无法在android的dvm下使用,如果JDK的Proxy也是生成字节码,那应该也不能在android下使用,但JDK的Proxy确可以在android下使用。
有没有大神帮推荐一个android下实现AOP比较好的方式(除了JDK的Proxy),谢谢。
另外一个问题,cglib和javassit动态生成字节码无法在android的dvm下使用,如果JDK的Proxy也是生成字节码,那应该也不能在android下使用,但JDK的Proxy确可以在android下使用。
有没有大神帮推荐一个android下实现AOP比较好的方式(除了JDK的Proxy),谢谢。
8 楼
FlyAway2
2013-09-04
都是强人啊
7 楼
qicen
2013-05-24
经过仔细的思考,发现性能的根本原因还是在于反射。
JdkHandler中的 return method.invoke(delegate, objects); 是影响性能的关键。
如果JAVAASSIST Bytecode Proxy生成的代理类,也是通过JdkHanlder去实现的话,性能就和JDK自身的动态代理没什么区别了。
JdkHandler中的 return method.invoke(delegate, objects); 是影响性能的关键。
如果JAVAASSIST Bytecode Proxy生成的代理类,也是通过JdkHanlder去实现的话,性能就和JDK自身的动态代理没什么区别了。
6 楼
qicen
2013-05-22
学习了,文章写的非常好。
不过如果用JAVAASSIST Bytecode Proxy去写一个共同的代理类的话,效率和JDK 的动态代理类是差不多的。我是用dubbo里的这个类去做的测试:com.alibaba.dubbo.common.bytecode.Proxy
private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception {
return (CountService) com.alibaba.dubbo.common.bytecode.Proxy.getProxy(CountService.class).newInstance(new JdkHandler(delegate));
}
这是测试结果:
Create JDK Proxy: 16 ms
Create JAVAASSIST Proxy: 47 ms
Create JAVAASSIST Bytecode Proxy: 94 ms
================
Run JDK Proxy: 952 ms, 1,481,161 t/s
Run JAVAASSIST Proxy: 1498 ms, 941,298 t/s
Run JAVAASSIST Bytecode Proxy: 999 ms, 1,411,476 t/s
----------------
Run JDK Proxy: 984 ms, 1,432,993 t/s
Run JAVAASSIST Proxy: 1483 ms, 950,819 t/s
Run JAVAASSIST Bytecode Proxy: 1108 ms, 1,272,622 t/s
----------------
Run JDK Proxy: 1015 ms, 1,389,227 t/s
Run JAVAASSIST Proxy: 1436 ms, 981,939 t/s
Run JAVAASSIST Bytecode Proxy: 1109 ms, 1,271,474 t/s
----------------
不过如果用JAVAASSIST Bytecode Proxy去写一个共同的代理类的话,效率和JDK 的动态代理类是差不多的。我是用dubbo里的这个类去做的测试:com.alibaba.dubbo.common.bytecode.Proxy
private static CountService createJavassistBytecodeDynamicProxy(CountService delegate) throws Exception {
return (CountService) com.alibaba.dubbo.common.bytecode.Proxy.getProxy(CountService.class).newInstance(new JdkHandler(delegate));
}
这是测试结果:
Create JDK Proxy: 16 ms
Create JAVAASSIST Proxy: 47 ms
Create JAVAASSIST Bytecode Proxy: 94 ms
================
Run JDK Proxy: 952 ms, 1,481,161 t/s
Run JAVAASSIST Proxy: 1498 ms, 941,298 t/s
Run JAVAASSIST Bytecode Proxy: 999 ms, 1,411,476 t/s
----------------
Run JDK Proxy: 984 ms, 1,432,993 t/s
Run JAVAASSIST Proxy: 1483 ms, 950,819 t/s
Run JAVAASSIST Bytecode Proxy: 1108 ms, 1,272,622 t/s
----------------
Run JDK Proxy: 1015 ms, 1,389,227 t/s
Run JAVAASSIST Proxy: 1436 ms, 981,939 t/s
Run JAVAASSIST Bytecode Proxy: 1109 ms, 1,271,474 t/s
----------------
5 楼
javatar
2012-02-27
chenchao051 写道
哈哈,至少博主和Gavin King做了相同的选择:
Hibernate, Environment类:
Hibernate, Environment类:
private static BytecodeProvider buildBytecodeProvider(String providerName){ if ( "javassist".equals( providerName ) ) { return new org.hibernate.bytecode.javassist.BytecodeProviderImpl(); }else if ( "cglib".equals( providerName ) ) { return new org.hibernate.bytecode.cglib.BytecodeProviderImpl(); } .......
Gavin King也是RedHat旗下的,当然选同宗的了,呵呵。
4 楼
chenchao051
2012-02-27
哈哈,至少博主和Gavin King做了相同的选择:
Hibernate, Environment类:
Hibernate, Environment类:
private static BytecodeProvider buildBytecodeProvider(String providerName){ if ( "javassist".equals( providerName ) ) { return new org.hibernate.bytecode.javassist.BytecodeProviderImpl(); }else if ( "cglib".equals( providerName ) ) { return new org.hibernate.bytecode.cglib.BytecodeProviderImpl(); } .......
3 楼
javatar
2012-02-23
billykinggym 写道
请问 用动态代理生成的bytecode是如何从jvm里导出来的?谢谢
可以用:
javap -c 类名
2 楼
billykinggym
2012-02-14
请问 用动态代理生成的bytecode是如何从jvm里导出来的?谢谢
1 楼
agapple
2011-03-31
这样的测试对cglib不公平,因为javassit采用的是直接调用,而cglib走了methodProxy.invoke(),说白了还是反射调用。
可以实施cglib的直接调用,比如使用的Dispatcher或则LazyLoader。最后的生成的字节就是一个直接调用,性能上就可以和javassist持平。
可以实施cglib的直接调用,比如使用的Dispatcher或则LazyLoader。最后的生成的字节就是一个直接调用,性能上就可以和javassist持平。
class DirectService implements Dispatcher { public Object loadObject() throws Exception { return service; } }
发表评论
-
能力成长模型
2012-05-09 00:28 22639最近看了温伯格1986年出版的《技术领导之路》, 很老的书,讲 ... -
以HTTL为例讲讲模块分包&领域模型&扩展框架
2011-10-09 20:08 16409注:该博客内容已加入 ... -
使用Map参数的Webx3扩展
2011-08-28 02:10 5847因Webx3是开源的,所以把这个简单的Webx3扩展发在博客上 ... -
Netty内存泄露
2011-08-02 20:09 24851转于自己在公司的Blog: ... -
Grizzly和Netty以及Mina简单性能对比
2011-07-17 02:48 29591转于自己在公司的Blog: http://pt.alibaba ... -
RPC框架几行代码就够了
2011-07-14 00:34 89419转于自己在公司的Blog: http://pt.alibaba ... -
魔鬼在细节中
2011-05-24 14:50 32255转于自己在公司的Blog: ... -
Dubbo扩展点重构
2011-05-12 22:09 38735转于自己在公司的Blog: http://pt.alibaba ... -
配置设计
2011-03-09 23:41 23412转于自己在公司的Blog: ... -
[转]HTML5设计原理
2011-03-09 22:57 7628Jeremy Keith在 Fronteers 2010 ... -
Hessian序列化不设SerializerFactory性能问题
2010-12-27 11:38 6371转于自己在公司的Blog: http://pt.alibaba ... -
防痴呆设计
2010-11-05 18:58 17489转于自己在公司的Blog: ... -
负载均衡扩展接口重构
2010-11-05 18:53 8619转于自己在公司的Blog: ... -
分布式服务框架常被质疑的价值
2010-11-05 18:52 5669转于自己在公司的Blog: http://pt.alibaba ... -
Hessian3.2.1在序列化32.5k字符串时的问题
2010-11-05 18:49 7094转于自己在公司的Blog: http://pt.alibaba ... -
一些设计上的基本常识
2010-07-05 19:28 27394转于自己在公司的Blog: ... -
谈谈扩充式扩展与增量式扩展
2010-06-12 19:46 18893转于自己在公司的Blog: http://pt.alibaba ... -
Scaling Architecture
2010-02-25 10:31 4044Scaling Second Life: http://p ... -
EBay SOA
2010-02-23 18:23 4729EBay SOA PPT -
服务化基础设施
2009-11-15 23:11 6209服务化,也可以叫SOA, ...
相关推荐
Android动态加载Apk-插件化技术(动态代理方案) 一. 什么是插件化 1. 主App(宿主App)加载插件apk的实现 2. 每个业务组件模块形成一个独立的Apk, 然后通过主App动态加载部署业务组件模块Apk的一种方案 二.插件化的...
局域网中代理服务器 路由器的配置方案 网络技术的飞速发展 使企事业单位局域网接入INTERNET共享资源的方式越来越多 就大多数而言 DDN专线以其性能稳定 扩充性好的优势成为普遍采用的方式 DDN方式的连接在硬件的需求...
java8 stream 源码 Java各种开源库积累 好好学习,天天向上。 演示内容 1)src/main/java org.xpen.audio 播放各种声音格式ogg,mp3,ape,flac org.xpen.chess.puzzle8 ...动态代理方案性能对比,比较了J
简介 Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate ...
经常有朋友困扰于Android上面实现推送的技术,希望知道各种方案的优缺点、性能、开发难度等,于是特意写了这篇文章。 方案一: Google官方的服务: 但,通过对比研究发现C2DM机制存在以下缺点: 1)GCM要求Android...
提出一种6LoWPAN嵌套移动网络路由优化方案,在此方案中,6LoWPAN...从理论和仿真两个角度对所提出的路由优化方案的路由优化开销、路由延迟及路由代价等性能参数进行了比较分析,分析结果验证了本方案的有效性和高效性。
网上搜了一圈,也没找到简单的解决方案。用NGINX折腾了一天,但搭出来的系统很不稳定。干脆用java自己写了个小程序,性能当然和squid、nginx之类的没法比,还好我们的系统负荷不是很重,运行了一个星期基本没问题。 ...
提出一种MANET地址自动配置方案, 给出了...对MANETConf、Prime DHCP以及本方案的性能参数进行了比较分析, 性能参数包括地址配置代价及地址配置延迟时间, 分析结果验证了本方案的地址配置代价更低, 地址配置延迟更短。
CORBA和移动代理是目前在分布式网络管理领域中应用得比较广泛的两种技术。在实际应用与研究领域中,它们都在不同的方面呈现出了各自的优势。但是,这两种技术又都存在着不同程度的缺陷。为了弥补移动代理和CORBA的...
基于国产密码算法 SM2 数字签名标准,设计了一种代理保护代理签名方案。...最后,利用C语言及Polarssl库对该方案进行了实现,并与SM2数字签名进行了性能比较。分析表明,该算法在性能上具有较好的可用性。
利用节点感知数据的空间相似性,提出了节点故障诊断的算法,通过对邻节点所感知的传感数据进行比较,从而确定检测节点的状态,并将测试状态向网络中其他相邻节点进行扩散。该算法对实现故障节点的检测具有较好的性能...
基于移动节点的能量级别,采取不同的转发概率,提出了一种Ad Hoc网络基于概率的路由协议——PBR,并与AODV协议进行了性能比较,仿真结果显示,PBR明显改善了系统的能量消耗,延长了网络的存活时间,并且具有较优的可...
WProxy 绿色免费版 WProxy是一款运行在windows系统上的代理服务器软件,可以给局域网的其他电脑提供代理上网服务,支持HTTP、...支持高并发处理,性能和squid代理比较毫不逊色,具体性能请参考“性能”。 终身免费。
解决方案 1 企业级整体解决方案 XX申请管理系统采用当今比较流行和技术比较先进的Microsoft.NET体系作为软件开 发平台和运行平台,以ASP.NET作为主流开发工具和软件运行的主要表现形式,采用当今 软件主要表现形式...
数据库的性能优化主要有两个方面:减少查询比较次数、减少资源的征用。 使用工具Sql Server Profiler优化数据库的性能,减少资源的征用 SqlServer Profiler的功能 Sql Server Profiler的用法 定义跟踪 ...
服务器故障应急响应方案 精品资料 服务器故障应急响应方案全文共8页,当前为第1页。服务器故障应急响应方案全文共8页,当前为第1页。 服务器故障应急响应方案全文共8页,当前为第1页。 服务器故障应急响应方案全文共...
10.7.6 CHM与OSWatcher对比 10.8本章小结 第11章 最高可用性 11.1最高可用性架构 11.1.1 Data Guard优势 11.1.2客户端Failover 11.1.3 Data Guard配置 11.1.4 Standby数据库 11.1.5 Data Guard保护模式 ...
针对代理移动IPv6(PMIPv6)中域间切换时延较大的问题,提出了一种基于PMIPv6的域间切换管理方案。新方案通过在PMIPv6域间发送PBU绑定更新消息,使得切换目标PMIPv6域提前知道移动节点(MN)的家乡网络前缀,避免了...