[编织消息框架][JAVA核心技术]jdk动态代理

java

需要用到的工具  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;

没有详细看到代理类指令

运行时生成的动态代理对象是可以导出到文件的,方法有两种

  1. 在代码中加入System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

  2. 在运行时加入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

回到顶部