`
javatar
  • 浏览: 1704539 次
  • 性别: 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的一种方案 二.插件化的...

    cglib动态代理

    8. **性能对比**:相对于JDK的动态代理,CGLib在某些场景下性能更优,因为它避免了接口调用的额外开销。然而,由于涉及到字节码操作,CGLib在初始化阶段可能比JDK代理慢。 9. **使用示例**:创建一个动态代理通常...

    通过动态代理模拟Spring AOP

    本篇文章将详细探讨如何通过Java的动态代理机制来模拟Spring AOP的核心概念。 首先,让我们了解什么是动态代理。在Java中,动态代理主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口...

    设计高性能的WCF解决方案 经典中的经典

    在构建高性能的Windows Communication Foundation(WCF)解决方案时,我们需要关注多个关键方面,这些方面将直接影响服务的性能、效率和可扩展性。本篇将详细探讨传输层、序列化器、编码器的选择以及客户端和服务端...

    面向无人机网络的属性代理签名方案.docx

    4. **性能分析**:从计算开销和通信开销两个方面评估该方案的效率,并与其他相关签名方案进行比较。结果显示,所提出的ABPS方案在保持与现有方案相似的通信开销的同时,显著减少了计算成本。 #### 相关工作概述 - ...

    基于代理的 Redis 集群解决方案,支持管道和动态扩展.zip

    Codis 是一个基于代理的高性能 Redis 集群解决方案,使用 Go 编写。它已投入生产,并在wandoujia.com和许多公司中广泛使用。您可以查看Codis Releases了解最新和最稳定的版本。捐款如果您想帮助我们维护这个项目,请...

    论文研究-高效的代理多重盲签名方案.pdf

    【标题】中所提及的“高效的代理多重盲签名方案”可能意味着所提出的方案在满足安全性要求的同时,具有更好的性能表现。这可能意味着该方案在保持高强度安全性的同时,通过优化算法,降低了计算资源的消耗,并减少了...

    TYPEC转换器方案 扩展坞方案 CS代理商型号详解.pdf

    2. 独特的接收机设计,低功耗和高性能。 3. 单电源设计可以节省BOM成本。 4. 可编程的SSC可以降低电磁干扰。 5. VGA的输出幅度自动校准算法,可以兼容各种阻抗。 6. DisplayPort自适应均衡算法,适应不同衰减的电缆...

    基于Linux内核2.4的高性能HTTP代理.pdf

    此外,文章还对比了Linux内核编程和用户态编程的优缺点,强调了内核编程在性能优化上的优势。通过实际测试数据,KHttpProxyd的性能表现明显优于其他HTTP代理软件,证明了这种设计和实现策略的有效性。 总的来说,...

    java8stream源码-daydayup:天天向上

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

    【McAfee】McAfee Web Gateway性能测试方案V1.docx

    在本方案中,Web Polygraph将被用来比较硬件MWG(McAfee Web Gateway)和软件MWG的性能差异。 测试环境基于CentOS 6.5 X86-64操作系统,这是由于Linux系统提供了稳定的基础,并且能够支持Web Polygraph的运行。为了...

    Java性能优化比较

    代理模式可以用于性能监控或拦截操作,提高代码的灵活性。这些模式的合理运用能提高代码的可读性和可维护性,间接提升性能。 在实际项目中,我们还需要借助各种性能分析工具,如JProfiler、VisualVM等,它们能帮助...

    路由NAT和代理的区别

    - **性能差异**:NAT因为工作在网络层,通常比工作在更高层的代理服务器速度更快。但如果代理服务器启用了缓存功能,则情况可能有所不同。 - **协议支持**:NAT支持更多的上层协议,几乎涵盖了所有的常见应用层协议...

    0多代理和动态环境中的轨迹规划器1

    实验部分可能会展示在不同场景下的性能比较,包括不同基函数下的轨迹质量和规划效率。此外,可能会对比集中式和去中心化方法的优劣,以证明MADER在实时性和安全性方面的优势。 IV. 结论与未来工作 MADER的提出为...

    吴炳锡:LVS、Nginx负载分衡构建实战,以及应用性能对比

    对于性能对比,LVS在处理大量连接时可能有优势,而Nginx在处理动态内容和复杂HTTP逻辑时更出色。 演讲可能详细讲解了LVS和Nginx的安装、配置、优化方法,以及在实际项目中如何选择合适的负载均衡策略。同时,通过...

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

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

    详细解析用Squid实现反向代理的方法

    反向代理服务器是提高WEB服务器性能和安全性的解决方案。它位于本地WEB服务器和Internet之间,承担对原始WEB服务器的静态页面的请求,防止原始服务器过载。反向代理服务器可以降低WEB服务器的负载,提高访问速度,...

    cglib__jar包.zip

    当一个类没有实现接口时,CGLIB可以作为JDK动态代理的一种替代方案。它创建目标类的子类,并在子类中拦截方法调用,从而实现动态代理。 2. **与ASM的关系**: - CGLIB底层依赖于ASM库来生成和操作字节码。ASM是一...

Global site tag (gtag.js) - Google Analytics