现在的位置: 首页 > 综合 > 正文

动态代理方案性能对比

2013年10月11日 ⁄ 综合 ⁄ 共 29925字 ⁄ 字号 评论关闭

因服务框架需要用动态代理生成客户端接口的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

}

作者原文:http://javatar.iteye.com/blog/814426

【上篇】
【下篇】

抱歉!评论已关闭.