V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lqw3030
V2EX  ›  Java

关于 Java 字节码的请教

  •  
  •   lqw3030 · 2020-04-14 09:45:48 +08:00 · 2810 次点击
    这是一个创建于 1472 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 例如,我有这么一份代码
    package lock;
    
    public class ByteCodeTest {
        private volatile String name="view";
        public void work(){
            name+="hello";
        }
    }
    
    • 编译后,通过字节码工具查看
    // class version 56.0 (56)
    // access flags 0x21
    public class lock/ByteCodeTest {
    
      // compiled from: ByteCodeTest.java
      // access flags 0x19
      public final static INNERCLASS java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup
    
      // access flags 0x42
      private volatile Ljava/lang/String; name
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 3 L0
        ALOAD 0
        INVOKESPECIAL java/lang/Object.<init> ()V
       L1
        LINENUMBER 4 L1
        ALOAD 0
        LDC "view"
        PUTFIELD lock/ByteCodeTest.name : Ljava/lang/String;
        RETURN
       L2
        LOCALVARIABLE this Llock/ByteCodeTest; L0 L2 0
        MAXSTACK = 2
        MAXLOCALS = 1
    
      // access flags 0x1
      public work()V
       L0
        LINENUMBER 6 L0
        ALOAD 0
        DUP
        GETFIELD lock/ByteCodeTest.name : Ljava/lang/String;
        INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;)Ljava/lang/String; [
          // handle kind 0x6 : INVOKESTATIC
          java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
          // arguments:
          "\u0001hello"
        ]
        PUTFIELD lock/ByteCodeTest.name : Ljava/lang/String;
       L1
        LINENUMBER 7 L1
        RETURN
       L2
        LOCALVARIABLE this Llock/ByteCodeTest; L0 L2 0
        MAXSTACK = 2
        MAXLOCALS = 1
    }
    
    • 想请教下如何阅读上述指令语法
    • 或是 google 什么关键字可以搜到相关内容
    第 1 条附言  ·  2020-04-22 15:54:26 +08:00
    • 这几天翻阅了书籍有些头绪,特来回帖,如果错误望指出

    代码

    package core.object_create;
    public class ObjectTest {
        private String name = "v2";
        public void add() {
            int i10 = -1;
            int i0 = 5;
            int i1 = 6;
            int i2 = 127;
            int i3 = 150;
            int sum = i10 + i0 + i1 + i2 + i3;
        }
    }
    

    字节码

    public class core/object_create/ObjectTest {
      private Ljava/lang/String; name
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 3 L0
        ALOAD 0 //将指定的引用类型本地变量推送至栈顶
        INVOKESPECIAL java/lang/Object.<init> ()V //调用超类构造方法,实例初始化方法,私有方法
       L1
        LINENUMBER 4 L1
        ALOAD 0
        LDC "v2" //将int, float或String型常量值从常量池中推送至栈顶
        PUTFIELD core/object_create/ObjectTest.name : Ljava/lang/String; //为指定的类的实例域赋值
        RETURN //从当前方法返回void
       L2
        LOCALVARIABLE this Lcore/object_create/ObjectTest; L0 L2 0
        MAXSTACK = 2 //代表了操作数栈(Operand Stacks)深度的最大值
        MAXLOCALS = 1 //代表了局部变量表所需的存储空间
      // access flags 0x1
      public add()V
       L0 //表示一个局部变量
        LINENUMBER 6 L0 //标识变量对应行
        ICONST_M1 //将int型-1推送至栈顶
        ISTORE 1 //将栈顶int型数值存入指定本地变量
       L1
        LINENUMBER 7 L1
        ICONST_5 //将int型5推送至栈顶
        ISTORE 2
       L2
        LINENUMBER 8 L2
        BIPUSH 6  //将单字节的常量值(-128~127)推送至栈顶
        ISTORE 3
       L3
        LINENUMBER 9 L3
        BIPUSH 127
        ISTORE 4
       L4
        LINENUMBER 10 L4
        SIPUSH 150
        ISTORE 5
       L5
        LINENUMBER 11 L5
        ILOAD 1 //将指定的int型本地变量推送至栈顶
        ILOAD 2 
        IADD  //将栈顶两int型数值相加并将结果压入栈顶
        ILOAD 3
        IADD
        ILOAD 4
        IADD
        ILOAD 5
        IADD
        ISTORE 6
       L6
        LINENUMBER 12 L6
        RETURN
       L7
        LOCALVARIABLE this Lcore/object_create/ObjectTest; L0 L7 0
        LOCALVARIABLE i10 I L1 L7 1
        LOCALVARIABLE i0 I L2 L7 2
        LOCALVARIABLE i1 I L3 L7 3
        LOCALVARIABLE i2 I L4 L7 4
        LOCALVARIABLE i3 I L5 L7 5
        LOCALVARIABLE sum I L6 L7 6
        MAXSTACK = 2
        MAXLOCALS = 7
    }
    
    11 条回复    2020-04-14 13:23:23 +08:00
    anerinck
        1
    anerinck  
       2020-04-14 09:52:50 +08:00
    我觉得直接看字节码的十六进制比阅读反编译要清楚。。如果是要了解指令的话不如去搜索一下 jvm 的指令集一类的?
    misaka19000
        2
    misaka19000  
       2020-04-14 09:53:04 +08:00
    《深入理解 Java 虚拟机》第 6 章
    CRUD
        3
    CRUD  
       2020-04-14 09:54:15 +08:00
    guxingke
        4
    guxingke  
       2020-04-14 10:15:11 +08:00
    https://github.com/guxingke/mini-jvm

    java 实现的解释字节码的虚拟机 可以了解一下
    lqw3030
        5
    lqw3030  
    OP
       2020-04-14 10:23:16 +08:00
    @anerinck
    @misaka19000
    @CRUD
    @guxingke
    太棒了,感谢各位😄
    maokabc
        6
    maokabc  
       2020-04-14 10:27:21 +08:00 via Android
    java 虚拟机规范,或者可以看 jasmin 的语法,感觉比这个更好理解,还能修改了再编译回 class
    choiwanxy
        7
    choiwanxy  
       2020-04-14 10:34:45 +08:00
    首先你要分得清哪里是什么,比如哪里是常量池,哪里是无参构架函数,哪里是方法对应的字节码。找到你要看的方法,看 jvm 指令,一个个去查是什么意思。
    lqw3030
        9
    lqw3030  
    OP
       2020-04-14 12:23:01 +08:00
    @maokabc
    @choiwanxy
    @itning
    有认真去看,感谢哈😄
    CFM880
        10
    CFM880  
       2020-04-14 13:09:45 +08:00
    jclasslib idea 插件,常量池,方法区,点击指令可以跳转到#3 楼说的网页中的指定指令
    CFM880
        11
    CFM880  
       2020-04-14 13:23:23 +08:00
    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
    这一章介绍了 ClassFile Structure,先整体了解字节码文件结构,结构嵌套结构,后面再到方法区的指令,比较容易一些,直接上指令集,可以按照字节码文件结构规定的字节来分析一下
    ClassFile {
    u4 magic; #u4 4 个字节魔数
    u2 minor_version; #2 个字节小版本号
    u2 major_version;
    u2 constant_pool_count;
    cp_info constant_pool[constant_pool_count-1];
    u2 access_flags;
    u2 this_class;
    u2 super_class;
    u2 interfaces_count;
    u2 interfaces[interfaces_count];
    u2 fields_count;
    field_info fields[fields_count];
    u2 methods_count;
    method_info methods[methods_count];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3769 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:32 · PVG 18:32 · LAX 03:32 · JFK 06:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.