• 深挖JDK动态代理(二):JDK动态生成后的字节码分析


    接上一篇文章深挖JDK动态代理(一)我们来分析一下JDK生成动态的代理类究竟是个什么东西

    1. 将生成的代理类编程一个class文件,通过以下方法

        public static void transClass() throws IOException {
            URL resource = rpcMain.class.getClass().getResource("/");
            byte[] bts = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{HelloService.class});
            File file = new File(resource.getPath(),"$Proxy0.class");
            if (!file.exists()){
                file.createNewFile();
            }
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bts);
            fos.flush();
            fos.close();
            System.out.println(resource.getPath());
        }
    

      主要是通过ProxyGenerator.generateProxyClass获取代理类,该方法第一个为生成该类的名字,可以通过DEBUG的形式获取,第二个参数为该动态代理类所实现的接口,然后获取其字节码文件,将该字节码文件写入到文件中

    2. 通过JD-GUI反编译代码

    import cn.lonecloud.study.dto.HelloDto;
    import cn.lonecloud.study.service.HelloService;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    //该类集成了Proxy代理类,和实现了HelloService接口
    public final class $Proxy0 extends Proxy implements HelloService {
        //声明了一系列方法,为啥要声明这个呢?请看最后面的实现类
        private static Method m1;
        private static Method m3;
        private static Method m2;
        private static Method m0;
    
        public $Proxy0(InvocationHandler var1) throws  {
            super(var1);
        }
        //重写Object类中equals方法
        public final boolean equals(Object var1) throws  {
            try {
                //都通过代理形式调用
                return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
        //实现getHello方法,通过代理形式
        public final HelloDto getHello(String var1) throws  {
            try {
                return (HelloDto)super.h.invoke(this, m3, new Object[]{var1});
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
       //重写toString方法
        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
        //重写hashCode方法
        public final int hashCode() throws  {
            try {
                return (Integer)super.h.invoke(this, m0, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
        //类初始化
        static {
            try {
                //加载Object类,并获取其equals方法
                m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
               //加载HelloService接口,并获取其getHello方法
                m3 = Class.forName("cn.lonecloud.study.service.HelloService").getMethod("getHello", Class.forName("java.lang.String"));
                //加载Object类,并获取其toString方法
                m2 = Class.forName("java.lang.Object").getMethod("toString");
                 //加载Object类,并获取其hashCode方法          
                m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
                    
    

      

    3. 将字节码通过 javap -verbose $Proxy0来获取字节码

    Classfile /Users/lonecloud/Documents/ideaCode/target/classes/$Proxy0.class
      Last modified 2018-6-9; size 2076 bytes
      MD5 checksum a9c607b2d44135c7672b37458cc16c23
    public final class $Proxy0 extends java.lang.reflect.Proxy implements cn.lonecloud.study.service.HelloService
      minor version: 0
      major version: 49
      flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
    Constant pool:
        #1 = Utf8               <init>
        #2 = Utf8               (Ljava/lang/reflect/InvocationHandler;)V
        #3 = Utf8               Code
        #4 = Utf8               Exceptions
        #5 = Utf8               java/lang/reflect/Proxy
        #6 = Class              #5            // java/lang/reflect/Proxy
        #7 = NameAndType        #1:#2         // "<init>":(Ljava/lang/reflect/InvocationHandler;)V
        #8 = Methodref          #6.#7         // java/lang/reflect/Proxy."<init>":(Ljava/lang/reflect/InvocationHandler;)V
        #9 = Utf8               m1
       #10 = Utf8               Ljava/lang/reflect/Method;
       #11 = Utf8               equals
       #12 = Utf8               (Ljava/lang/Object;)Z
       #13 = Utf8               h
       #14 = Utf8               Ljava/lang/reflect/InvocationHandler;
       #15 = NameAndType        #13:#14       // h:Ljava/lang/reflect/InvocationHandler;
       #16 = Fieldref           #6.#15        // java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
       #17 = Utf8               $Proxy0
       #18 = Class              #17           // $Proxy0
       #19 = NameAndType        #9:#10        // m1:Ljava/lang/reflect/Method;
       #20 = Fieldref           #18.#19       // $Proxy0.m1:Ljava/lang/reflect/Method;
       #21 = Utf8               java/lang/Object
       #22 = Class              #21           // java/lang/Object
       #23 = Utf8               java/lang/reflect/InvocationHandler
       #24 = Class              #23           // java/lang/reflect/InvocationHandler
       #25 = Utf8               invoke
       #26 = Utf8               (Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
       #27 = NameAndType        #25:#26       // invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
       #28 = InterfaceMethodref #24.#27       // java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
       #29 = Utf8               java/lang/Boolean
       #30 = Class              #29           // java/lang/Boolean
       #31 = Utf8               booleanValue
       #32 = Utf8               ()Z
       #33 = NameAndType        #31:#32       // booleanValue:()Z
       #34 = Methodref          #30.#33       // java/lang/Boolean.booleanValue:()Z
       #35 = Utf8               java/lang/Error
       #36 = Class              #35           // java/lang/Error
       #37 = Utf8               java/lang/RuntimeException
       #38 = Class              #37           // java/lang/RuntimeException
       #39 = Utf8               java/lang/Throwable
       #40 = Class              #39           // java/lang/Throwable
       #41 = Utf8               java/lang/reflect/UndeclaredThrowableException
       #42 = Class              #41           // java/lang/reflect/UndeclaredThrowableException
       #43 = Utf8               (Ljava/lang/Throwable;)V
       #44 = NameAndType        #1:#43        // "<init>":(Ljava/lang/Throwable;)V
       #45 = Methodref          #42.#44       // java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
       #46 = Utf8               m3
       #47 = Utf8               getHello
       #48 = Utf8               (Ljava/lang/String;)Lcn/lonecloud/study/dto/HelloDto;
       #49 = NameAndType        #46:#10       // m3:Ljava/lang/reflect/Method;
       #50 = Fieldref           #18.#49       // $Proxy0.m3:Ljava/lang/reflect/Method;
       #51 = Utf8               cn/lonecloud/study/dto/HelloDto
       #52 = Class              #51           // cn/lonecloud/study/dto/HelloDto
       #53 = Utf8               m2
       #54 = Utf8               toString
       #55 = Utf8               ()Ljava/lang/String;
       #56 = NameAndType        #53:#10       // m2:Ljava/lang/reflect/Method;
       #57 = Fieldref           #18.#56       // $Proxy0.m2:Ljava/lang/reflect/Method;
       #58 = Utf8               java/lang/String
       #59 = Class              #58           // java/lang/String
       #60 = Utf8               m0
       #61 = Utf8               hashCode
       #62 = Utf8               ()I
       #63 = NameAndType        #60:#10       // m0:Ljava/lang/reflect/Method;
       #64 = Fieldref           #18.#63       // $Proxy0.m0:Ljava/lang/reflect/Method;
       #65 = Utf8               java/lang/Integer
       #66 = Class              #65           // java/lang/Integer
       #67 = Utf8               intValue
       #68 = NameAndType        #67:#62       // intValue:()I
       #69 = Methodref          #66.#68       // java/lang/Integer.intValue:()I
       #70 = Utf8               <clinit>
       #71 = Utf8               ()V
       #72 = Utf8               java.lang.Object
       #73 = String             #72           // java.lang.Object
       #74 = Utf8               java/lang/Class
       #75 = Class              #74           // java/lang/Class
       #76 = Utf8               forName
       #77 = Utf8               (Ljava/lang/String;)Ljava/lang/Class;
       #78 = NameAndType        #76:#77       // forName:(Ljava/lang/String;)Ljava/lang/Class;
       #79 = Methodref          #75.#78       // java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
       #80 = String             #11           // equals
       #81 = Utf8               getMethod
       #82 = Utf8               (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
       #83 = NameAndType        #81:#82       // getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
       #84 = Methodref          #75.#83       // java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
       #85 = Utf8               cn.lonecloud.study.service.HelloService
       #86 = String             #85           // cn.lonecloud.study.service.HelloService
       #87 = String             #47           // getHello
       #88 = Utf8               java.lang.String
       #89 = String             #88           // java.lang.String
       #90 = String             #54           // toString
       #91 = String             #61           // hashCode
       #92 = Utf8               java/lang/NoSuchMethodException
       #93 = Class              #92           // java/lang/NoSuchMethodException
       #94 = Utf8               java/lang/NoSuchMethodError
       #95 = Class              #94           // java/lang/NoSuchMethodError
       #96 = Utf8               getMessage
       #97 = NameAndType        #96:#55       // getMessage:()Ljava/lang/String;
       #98 = Methodref          #40.#97       // java/lang/Throwable.getMessage:()Ljava/lang/String;
       #99 = Utf8               (Ljava/lang/String;)V
      #100 = NameAndType        #1:#99        // "<init>":(Ljava/lang/String;)V
      #101 = Methodref          #95.#100      // java/lang/NoSuchMethodError."<init>":(Ljava/lang/String;)V
      #102 = Utf8               java/lang/ClassNotFoundException
      #103 = Class              #102          // java/lang/ClassNotFoundException
      #104 = Utf8               java/lang/NoClassDefFoundError
      #105 = Class              #104          // java/lang/NoClassDefFoundError
      #106 = Methodref          #105.#100     // java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
      #107 = Utf8               cn/lonecloud/study/service/HelloService
      #108 = Class              #107          // cn/lonecloud/study/service/HelloService
    {
      public $Proxy0(java.lang.reflect.InvocationHandler) throws ;
        descriptor: (Ljava/lang/reflect/InvocationHandler;)V
        flags: ACC_PUBLIC
        Code:
          stack=10, locals=2, args_size=2
             0: aload_0
             1: aload_1
             2: invokespecial #8                  // Method java/lang/reflect/Proxy."<init>":(Ljava/lang/reflect/InvocationHandler;)V
             5: return
        Exceptions:
          throws
    
      public final boolean equals(java.lang.Object) throws ;
        descriptor: (Ljava/lang/Object;)Z
        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     #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."<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
    
      public final cn.lonecloud.study.dto.HelloDto getHello(java.lang.String) throws ;
        descriptor: (Ljava/lang/String;)Lcn/lonecloud/study/dto/HelloDto;
        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     #50                 // Field m3: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     #52                 // class cn/lonecloud/study/dto/HelloDto
            24: areturn
            25: athrow
            26: astore_2
            27: new           #42                 // class java/lang/reflect/UndeclaredThrowableException
            30: dup
            31: aload_2
            32: invokespecial #45                 // Method java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
            35: athrow
          Exception table:
             from    to  target type
                 0    25    25   Class java/lang/Error
                 0    25    25   Class java/lang/RuntimeException
                 0    25    26   Class java/lang/Throwable
        Exceptions:
          throws
    
      public final java.lang.String toString() throws ;
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC, ACC_FINAL
        Code:
          stack=10, locals=2, args_size=1
             0: aload_0
             1: getfield      #16                 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
             4: aload_0
             5: getstatic     #57                 // 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     #59                 // 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."<init>":(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
        Exceptions:
          throws
    
      public final int hashCode() throws ;
        descriptor: ()I
        flags: ACC_PUBLIC, ACC_FINAL
        Code:
          stack=10, locals=2, args_size=1
             0: aload_0
             1: getfield      #16                 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
             4: aload_0
             5: getstatic     #64                 // 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     #66                 // class java/lang/Integer
            17: invokevirtual #69                 // 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."<init>":(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
        Exceptions:
          throws
    
      static {} throws ;
        descriptor: ()V
        flags: ACC_STATIC
        Code:
          stack=10, locals=2, args_size=0
             0: ldc           #73                 // String java.lang.Object
             2: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
             5: ldc           #80                 // String equals
             7: iconst_1
             8: anewarray     #75                 // class java/lang/Class
            11: dup
            12: iconst_0
            13: ldc           #73                 // String java.lang.Object
            15: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
            18: aastore
            19: invokevirtual #84                 // 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           #86                 // String cn.lonecloud.study.service.HelloService
            27: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
            30: ldc           #87                 // String getHello
            32: iconst_1
            33: anewarray     #75                 // class java/lang/Class
            36: dup
            37: iconst_0
            38: ldc           #89                 // String java.lang.String
            40: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
            43: aastore
            44: invokevirtual #84                 // Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
            47: putstatic     #50                 // Field m3:Ljava/lang/reflect/Method;
            50: ldc           #73                 // String java.lang.Object
            52: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
            55: ldc           #90                 // String toString
            57: iconst_0
            58: anewarray     #75                 // class java/lang/Class
            61: invokevirtual #84                 // Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
            64: putstatic     #57                 // Field m2:Ljava/lang/reflect/Method;
            67: ldc           #73                 // String java.lang.Object
            69: invokestatic  #79                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
            72: ldc           #91                 // String hashCode
            74: iconst_0
            75: anewarray     #75                 // class java/lang/Class
            78: invokevirtual #84                 // Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
            81: putstatic     #64                 // Field m0:Ljava/lang/reflect/Method;
            84: return
            85: astore_1
            86: new           #95                 // class java/lang/NoSuchMethodError
            89: dup
            90: aload_1
            91: invokevirtual #98                 // Method java/lang/Throwable.getMessage:()Ljava/lang/String;
            94: invokespecial #101                // Method java/lang/NoSuchMethodError."<init>":(Ljava/lang/String;)V
            97: athrow
            98: astore_1
            99: new           #105                // class java/lang/NoClassDefFoundError
           102: dup
           103: aload_1
           104: invokevirtual #98                 // Method java/lang/Throwable.getMessage:()Ljava/lang/String;
           107: invokespecial #106                // Method java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
           110: athrow
          Exception table:
             from    to  target type
                 0    85    85   Class java/lang/NoSuchMethodException
                 0    85    98   Class java/lang/ClassNotFoundException
        Exceptions:
          throws
    View Code

    总结: 代理对象生成类:

    1. 该代理对象会将该接口的的方法进行一次封装通过调用super.h.invoke(this, m0, (Object[])null);将执行之前定义的InvolicationHandler类中的invoke方法然后再调用我们之前编写的类方法。

    2. 会将Object类中的toString,equals,hashCode这些方法进行代理

    3. 将InvocationHandler通过成员变量的形式传递到类中

      

  • 相关阅读:
    Java正式day_06——数组排序
    别只知道策略模式+简单工厂,试试更香的策略模式+抽象工厂!
    图解连接阿里云(一)创建阿里云物联网平台产品和设备,使用MQTT.fx快速体验
    嵌入式交叉编译GDB,结合vscode图形化调试C和C++代码 coredump定位段错误
    内核链表之list_for_eacy_entry手绘图解
    makefile实验三 理解make工作的基本原则
    玩转Libmodbus(一) 搭建开发环境
    RT-Thread的C语言多态风格展示
    C++函数默认参数 详解
    杂类-边学边记
  • 原文地址:https://www.cnblogs.com/lonecloud/p/9158668.html
Copyright © 2020-2023  润新知