[编织消息框架][JAVA核心技术]jdk动态代理
需要用到的工具 jdk : javac javap
class 反编译 :JD-GUI http://jd.benow.ca/
先来看下动态代理" title="jdk动态代理">jdk动态代理跟native性能比较
1 package com.eyu.onequeue;2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6
7 public class TestProxy {
8 public interface UserService {
9 public String getName(int id);
10
11 public Integer getAge(int id);
12 }
13
14 public static class UserServiceImpl implements UserService {
15
16 @Override
17 public String getName(int id) {
18 return "name : " + id;
19 }
20
21 @Override
22 public Integer getAge(int id) {
23 return id;
24 }
25 };
26
27 public static void main(String[] args) {
28 testNative();
29 testJdk();
30 }
31
32 public static void testJdk() {
33 UserService impTarget = new UserServiceImpl();
34 // 代理处理逻辑
35 InvocationHandler handler = new InvocationHandler() {
36
37 @Override
38 public Object invoke(Object target, Method method, Object[] args) throws Throwable {
39 return method.invoke(impTarget, args);
40 }
41 };
42 // Proxy.newProxyInstance(ClassLoader/**ClassLoader 没有特别处理 拿默认即可 **/,
43 // Class<?>[]/**代理接口类**/, InvocationHandler /**代理处理逻辑**/)
44 UserService proxy = (UserService) Proxy.newProxyInstance(TestProxy.class.getClassLoader(), new Class[] { UserService.class }, handler);
45
46 run("jdk", proxy);
47 }
48
49 public static void testNative() {
50 UserService impTarget = new UserServiceImpl();
51 run("native", impTarget);
52 }
53
54 private static void run(String tag, UserService impTarget) {
55 int c = 15;
56 System.out.println();
57 while (c-- > 0) {
58 long start = System.currentTimeMillis();
59 for (int i = 0; i < 10000000; i++) {
60 impTarget.getName(11);
61 }
62 long end = System.currentTimeMillis();
63 System.out.print(tag + ": " + (end - start) + " ");
64 }
65 }
66 }
运行结果:
native: 175 native: 182 native: 126 native: 172 native: 126 native: 127 native: 127 native: 126 native: 127 native: 126 native: 126 native: 128 native: 126 native: 127 native: 126
jdk: 214 jdk: 170 jdk: 169 jdk: 169 jdk: 170 jdk: 170 jdk: 170 jdk: 170 jdk: 170 jdk: 172 jdk: 169 jdk: 172 jdk: 169 jdk: 171 jdk: 169
先运行预热,看出执行五次之后比较稳定
jdk动态代理使用非常简单,使用Proxy.newProxyInstance 静态方法即可
接下来我们看下class指令
javac -encoding UTF-8 -d . TestProxy.java
javap -v com\eyu\onequeue\TestProxy.class > s.txt
其中
// Method java/lang/reflect/Proxy.newProxyInstance:(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;
没有详细看到代理类指令
运行时生成的动态代理对象是可以导出到文件的,方法有两种
- 在代码中加入
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
- 在运行时加入jvm 参数
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
我们在main方法加一行System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 然后执行一下
1 public static void main(String[] args) {2 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
3 //省略
4 }
这时在包下会多出$Proxy0.class文件
proxy0.class用jd-gui打开
1 package com.sun.proxy;2
3 import com.eyu.onequeue.TestProxy.UserService;
4 import java.lang.reflect.InvocationHandler;
5 import java.lang.reflect.Method;
6 import java.lang.reflect.Proxy;
7 import java.lang.reflect.UndeclaredThrowableException;
8
9 public final class $Proxy0
10 extends Proxy
11 implements TestProxy.UserService
12 {
13 private static Method m1;
14 private static Method m2;
15 private static Method m3;
16 private static Method m4;
17 private static Method m0;
18
19 public $Proxy0(InvocationHandler paramInvocationHandler)
20 {
21 super(paramInvocationHandler);
22 }
23
24 public final boolean equals(Object paramObject)
25 {
26 try
27 {
28 return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
29 }
30 catch (Error|RuntimeException localError)
31 {
32 throw localError;
33 }
34 catch (Throwable localThrowable)
35 {
36 throw new UndeclaredThrowableException(localThrowable);
37 }
38 }
39
40 public final String toString()
41 {
42 try
43 {
44 return (String)this.h.invoke(this, m2, null);
45 }
46 catch (Error|RuntimeException localError)
47 {
48 throw localError;
49 }
50 catch (Throwable localThrowable)
51 {
52 throw new UndeclaredThrowableException(localThrowable);
53 }
54 }
55
56 public final String getName(int paramInt)
57 {
58 try
59 {
60 return (String)this.h.invoke(this, m3, new Object[] { Integer.valueOf(paramInt) });
61 }
62 catch (Error|RuntimeException localError)
63 {
64 throw localError;
65 }
66 catch (Throwable localThrowable)
67 {
68 throw new UndeclaredThrowableException(localThrowable);
69 }
70 }
71
72 public final Integer getAge(int paramInt)
73 {
74 try
75 {
76 return (Integer)this.h.invoke(this, m4, new Object[] { Integer.valueOf(paramInt) });
77 }
78 catch (Error|RuntimeException localError)
79 {
80 throw localError;
81 }
82 catch (Throwable localThrowable)
83 {
84 throw new UndeclaredThrowableException(localThrowable);
85 }
86 }
87
88 public final int hashCode()
89 {
90 try
91 {
92 return ((Integer)this.h.invoke(this, m0, null)).intValue();
93 }
94 catch (Error|RuntimeException localError)
95 {
96 throw localError;
97 }
98 catch (Throwable localThrowable)
99 {
100 throw new UndeclaredThrowableException(localThrowable);
101 }
102 }
103
104 static
105 {
106 try
107 {
108 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
109 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
110 m3 = Class.forName("com.eyu.onequeue.TestProxy$UserService").getMethod("getName", new Class[] { Integer.TYPE });
111 m4 = Class.forName("com.eyu.onequeue.TestProxy$UserService").getMethod("getAge", new Class[] { Integer.TYPE });
112 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
113 return;
114 }
115 catch (NoSuchMethodException localNoSuchMethodException)
116 {
117 throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
118 }
119 catch (ClassNotFoundException localClassNotFoundException)
120 {
121 throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
122 }
123 }
124 }
proxy0
proxy0分析分两部份
1.在内存动态生成代理类 以$proxy 开头
$Proxy0 extends Proxy implements XXXXProxy.UserService
并初始化InvocationHandler 同绑定 Method
1 public $Proxy0(InvocationHandler paramInvocationHandler)2 {
3 super(paramInvocationHandler);
4 }
5
6 static
7 {
8 try
9 {
10 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
11 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
12 m3 = Class.forName("com.eyu.onequeue.TestProxy$UserService").getMethod("getName", new Class[] { Integer.TYPE });
13 m4 = Class.forName("com.eyu.onequeue.TestProxy$UserService").getMethod("getAge", new Class[] { Integer.TYPE });
14 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
15 return;
16 }
17 .....
18 }
第二部分:代理原对象所有方法实现调用InvocationHandler 类的 Object invoke(Object target, Method method, Object[] args) throws Throwable 方法 再通过method反射invoke
public final String getName(int paramInt){
try
{
return (String)this.h.invoke(this, m3, new Object[] { Integer.valueOf(paramInt) });
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
我们通过生成指令 E:\java\findme\com\sun\proxy>javap -v $Proxy0.class > d.txt
来查看代理过的getName方法共多少条指令
public final java.lang.String getName(int) throws ;descriptor: (I)Ljava/lang/String;
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=10, locals=3, args_size=2
0: aload_0
1: getfield #16 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #57 // Field m3:Ljava/lang/reflect/Method;
8: iconst_1
9: anewarray #22 // class java/lang/Object
12: dup
13: iconst_0
14: iload_1
15: invokestatic #63 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
18: aastore
19: invokeinterface #28, 4 // InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
24: checkcast #52 // class java/lang/String
27: areturn
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."<init>":(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
Exceptions:
throws
如果不出错,到 27:areturn 至少要执行到13条指令 java8对动态代理有优化过
结论是:jdk动态代理比原生调用只慢几十毫秒,这点可以忽略不计
以上是 [编织消息框架][JAVA核心技术]jdk动态代理 的全部内容, 来源链接: utcz.com/z/392152.html