`
javatar
  • 浏览: 1677662 次
  • 性别: Icon_minigender_1
  • 来自: 杭州699号
社区版块
存档分类
最新评论

动态代理方案性能对比

阅读更多
转于自己在公司的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)
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  
如果要用可以参考如下
  • 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更好。

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更好。
11 楼 lovearpu 2016-11-25  
[color=gray][b]
[flash=200,200][url][img][list]
[*]
引用
[u][i][/i][/u]
[/list][/img][/url][/flash]
[/b][/color]
" 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),谢谢。
8 楼 FlyAway2 2013-09-04  
都是强人啊
7 楼 qicen 2013-05-24  
经过仔细的思考,发现性能的根本原因还是在于反射。
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
----------------
5 楼 javatar 2012-02-27  
chenchao051 写道
哈哈,至少博主和Gavin King做了相同的选择:

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类:

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持平。

    class DirectService implements Dispatcher {

        public Object loadObject() throws Exception {
            return service;
        }

    }

相关推荐

    Adroid动态加载Apk-插件化技术框架(动态代理方案)源码

    Android动态加载Apk-插件化技术(动态代理方案) 一. 什么是插件化 1. 主App(宿主App)加载插件apk的实现 2. 每个业务组件模块形成一个独立的Apk, 然后通过主App动态加载部署业务组件模块Apk的一种方案 二.插件化的...

    局域网中代理服务器、路由器的配置方案

    局域网中代理服务器 路由器的配置方案 网络技术的飞速发展 使企事业单位局域网接入INTERNET共享资源的方式越来越多 就大多数而言 DDN专线以其性能稳定 扩充性好的优势成为普遍采用的方式 DDN方式的连接在硬件的需求...

    java8stream源码-daydayup:天天向上

    java8 stream 源码 Java各种开源库积累 好好学习,天天向上。 演示内容 1)src/main/java org.xpen.audio 播放各种声音格式ogg,mp3,ape,flac org.xpen.chess.puzzle8 ...动态代理方案性能对比,比较了J

    提升Ruby on Rails性能的几个解决方案

    简介 Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate ...

    安卓推送方案及比较

    经常有朋友困扰于Android上面实现推送的技术,希望知道各种方案的优缺点、性能、开发难度等,于是特意写了这篇文章。 方案一: Google官方的服务: 但,通过对比研究发现C2DM机制存在以下缺点: 1)GCM要求Android...

    论文研究-6LoWPAN嵌套移动网络路由优化方案.pdf

    提出一种6LoWPAN嵌套移动网络路由优化方案,在此方案中,6LoWPAN...从理论和仿真两个角度对所提出的路由优化方案的路由优化开销、路由延迟及路由代价等性能参数进行了比较分析,分析结果验证了本方案的有效性和高效性。

    HTTPS 代理-SNI Proxy-WebSocket-Java

    网上搜了一圈,也没找到简单的解决方案。用NGINX折腾了一天,但搭出来的系统很不稳定。干脆用java自己写了个小程序,性能当然和squid、nginx之类的没法比,还好我们的系统负荷不是很重,运行了一个星期基本没问题。 ...

    论文研究-一种MANET地址自动配置方案.pdf

    提出一种MANET地址自动配置方案, 给出了...对MANETConf、Prime DHCP以及本方案的性能参数进行了比较分析, 性能参数包括地址配置代价及地址配置延迟时间, 分析结果验证了本方案的地址配置代价更低, 地址配置延迟更短。

    论文研究-关于CORBA与移动代理结合用于网络管理的研究.pdf

    CORBA和移动代理是目前在分布式网络管理领域中应用得比较广泛的两种技术。在实际应用与研究领域中,它们都在不同的方面呈现出了各自的优势。但是,这两种技术又都存在着不同程度的缺陷。为了弥补移动代理和CORBA的...

    基于SM2的代理保护代理签名的设计与实现

    基于国产密码算法 SM2 数字签名标准,设计了一种代理保护代理签名方案。...最后,利用C语言及Polarssl库对该方案进行了实现,并与SM2数字签名进行了性能比较。分析表明,该算法在性能上具有较好的可用性。

    论文研究-)门限代理签名方案.pdf

    利用节点感知数据的空间相似性,提出了节点故障诊断的算法,通过对邻节点所感知的传感数据进行比较,从而确定检测节点的状态,并将测试状态向网络中其他相邻节点进行扩散。该算法对实现故障节点的检测具有较好的性能...

    论文研究-前向安全的代理盲签名方案.pdf

    基于移动节点的能量级别,采取不同的转发概率,提出了一种Ad Hoc网络基于概率的路由协议——PBR,并与AODV协议进行了性能比较,仿真结果显示,PBR明显改善了系统的能量消耗,延长了网络的存活时间,并且具有较优的可...

    WProxy.rar

    WProxy 绿色免费版 WProxy是一款运行在windows系统上的代理服务器软件,可以给局域网的其他电脑提供代理上网服务,支持HTTP、...支持高并发处理,性能和squid代理比较毫不逊色,具体性能请参考“性能”。 终身免费。

    XX系统方案设计.doc

    解决方案 1 企业级整体解决方案 XX申请管理系统采用当今比较流行和技术比较先进的Microsoft.NET体系作为软件开 发平台和运行平台,以ASP.NET作为主流开发工具和软件运行的主要表现形式,采用当今 软件主要表现形式...

    SQLServer安全及性能优化

    数据库的性能优化主要有两个方面:减少查询比较次数、减少资源的征用。 使用工具Sql Server Profiler优化数据库的性能,减少资源的征用 SqlServer Profiler的功能 Sql Server Profiler的用法  定义跟踪  ...

    服务器故障应急响应方案.docx

    服务器故障应急响应方案 精品资料 服务器故障应急响应方案全文共8页,当前为第1页。服务器故障应急响应方案全文共8页,当前为第1页。 服务器故障应急响应方案全文共8页,当前为第1页。 服务器故障应急响应方案全文共...

    构建最高可用Oracle数据库系统 Oracle 11gR2 RAC管理、维护与性能优化

    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保护模式 ...

    论文研究-基于PMIPv6的域间切换管理方法及性能分析.pdf

    针对代理移动IPv6(PMIPv6)中域间切换时延较大的问题,提出了一种基于PMIPv6的域间切换管理方案。新方案通过在PMIPv6域间发送PBU绑定更新消息,使得切换目标PMIPv6域提前知道移动节点(MN)的家乡网络前缀,避免了...

Global site tag (gtag.js) - Google Analytics