【JVM学习笔记】字节码文件结构实例

上一篇笔记的内容大部分没有实际动手操作,因此决定完成这个完整的练习并记录下来。

源代码如下:

package com.learn.jvm;

/**
 * @author
 * @Description
 * @date 2019/09/05 16:31
 */
public class Test {
    String str = "Welcome";
    private int x = 5;
    public static Integer num = 10;

    public static void main(String[] args) {
        Test test = new Test();
        test.setX(8);
        num = 20;
    }

    public void setX(int x) {
        this.x = x;
    }
}

编译后在Windows平台下用HexEditor打开,得到结果如下,由于该软件似乎不支持将内容复制出来,因此截图

javap -verbose的输出结果如下

D:\workspace-learn\common-learn\learn-classloader\target\classes\com\learn\jvm>javap -verbose Test
警告: 二进制文件Test包含com.learn.jvm.Test
Classfile /D:/workspace-learn/common-learn/learn-classloader/target/classes/com/learn/jvm/Test.class
  Last modified 2019-9-5; size 814 bytes
  MD5 checksum d9651b05ecd94c86c354ab2551983cea
  Compiled from "Test.java"
public class com.learn.jvm.Test
  SourceFile: "Test.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #10.#34        //  java/lang/Object."<init>":()V
   #2 = String             #35            //  Welcome
   #3 = Fieldref           #5.#36         //  com/learn/jvm/Test.str:Ljava/lang/String;
   #4 = Fieldref           #5.#37         //  com/learn/jvm/Test.x:I
   #5 = Class              #38            //  com/learn/jvm/Test
   #6 = Methodref          #5.#34         //  com/learn/jvm/Test."<init>":()V
   #7 = Methodref          #5.#39         //  com/learn/jvm/Test.setX:(I)V
   #8 = Methodref          #40.#41        //  java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #9 = Fieldref           #5.#42         //  com/learn/jvm/Test.num:Ljava/lang/Integer;
  #10 = Class              #43            //  java/lang/Object
  #11 = Utf8               str
  #12 = Utf8               Ljava/lang/String;
  #13 = Utf8               x
  #14 = Utf8               I
  #15 = Utf8               num
  #16 = Utf8               Ljava/lang/Integer;
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               LocalVariableTable
  #22 = Utf8               this
  #23 = Utf8               Lcom/learn/jvm/Test;
  #24 = Utf8               main
  #25 = Utf8               ([Ljava/lang/String;)V
  #26 = Utf8               args
  #27 = Utf8               [Ljava/lang/String;
  #28 = Utf8               test
  #29 = Utf8               setX
  #30 = Utf8               (I)V
  #31 = Utf8               <clinit>
  #32 = Utf8               SourceFile
  #33 = Utf8               Test.java
  #34 = NameAndType        #17:#18        //  "<init>":()V
  #35 = Utf8               Welcome
  #36 = NameAndType        #11:#12        //  str:Ljava/lang/String;
  #37 = NameAndType        #13:#14        //  x:I
  #38 = Utf8               com/learn/jvm/Test
  #39 = NameAndType        #29:#30        //  setX:(I)V
  #40 = Class              #44            //  java/lang/Integer
  #41 = NameAndType        #45:#46        //  valueOf:(I)Ljava/lang/Integer;
  #42 = NameAndType        #15:#16        //  num:Ljava/lang/Integer;
  #43 = Utf8               java/lang/Object
  #44 = Utf8               java/lang/Integer
  #45 = Utf8               valueOf
  #46 = Utf8               (I)Ljava/lang/Integer;
{
  java.lang.String str;
    flags:

  public static java.lang.Integer num;
    flags: ACC_PUBLIC, ACC_STATIC

  public com.learn.jvm.Test();
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String Welcome
         7: putfield      #3                  // Field str:Ljava/lang/String;
        10: aload_0
        11: iconst_5
        12: putfield      #4                  // Field x:I
        15: return
      LineNumberTable:
        line 8: 0
        line 9: 4
        line 10: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      16     0  this   Lcom/learn/jvm/Test;

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #5                  // class com/learn/jvm/Test
         3: dup
         4: invokespecial #6                  // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: bipush        8
        11: invokevirtual #7                  // Method setX:(I)V
        14: bipush        20
        16: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        19: putstatic     #9                  // Field num:Ljava/lang/Integer;
        22: return
      LineNumberTable:
        line 14: 0
        line 15: 8
        line 16: 14
        line 17: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0      23     0  args   [Ljava/lang/String;
               8      15     1  test   Lcom/learn/jvm/Test;

  public void setX(int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: iload_1
         2: putfield      #4                  // Field x:I
         5: return
      LineNumberTable:
        line 20: 0
        line 21: 5
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0       6     0  this   Lcom/learn/jvm/Test;
               0       6     1     x   I

  static {};
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        10
         2: invokestatic  #8                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: putstatic     #9                  // Field num:Ljava/lang/Integer;
         8: return
      LineNumberTable:
        line 11: 0
}

同时贴出Java字节码整体结构图便于对比查看

以下开始逐个字节进行分析

第1~4个字节:ca fe ba be 为魔数

第5~6个字节:00 00 代表 minor version ,值为0

第7~8个字节:00 33 代表 major version ,值为51

第9~10个字节:00 2f ,换算成十进制为 32+15 = 47 ,代表常量池中共有46个常量(除去一个为null保留的常量),我们通过查看上面 avap -verbose打印出来的信息可以验证,确实是这样的

接下来是具体的常量分析,所以将常量池中的数据类型结构贴出来

(以下为第1个变量)

第11~12个字节:0a 00 

猜你喜欢

转载自www.cnblogs.com/heben/p/11468285.html