重學JVM之class文件結構

先準備一個簡單的java文件

public class Person {
    private String name = "jack";
    private int age;
    private final double salary = 100;
    private static String address;
    private final static String hobby = "programming";
    private static Object obj = new Object();
    public void say(){
        System.out.println("person say ...");
    }
    public static int calc(int op1,int op2){
        op1 =3;
        int result = op1 + op2;
        Object object = new Object();
        return result;
    }
    public static void main(String[] args) {
        calc(1,2);
    }
}

經過javac命令編譯後得到一個class文件,用UE編輯器打開後得到的class文件格式是如下這樣的
在這裏插入圖片描述
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html 的官網可以看到,class文件的結構是由以下的格式進行排列的,u1,u2,u4,u8分別代表1個字節,2個字節,4個字節,8個字節,以“_info”結尾的則稱爲表。class文件的順序,長度都是都是固定,不可以隨便變動
在這裏插入圖片描述
對應中文版本如下
在這裏插入圖片描述
class文件的第一個首先是魔數,魔數佔4個字節,也就是CA FE BA BE,作用是確定文件是否爲一個能被虛擬機識別的class文件 ,魔數之後就是次版本號(即00 00);主版本號(00 34);
各個版本的對應關係,本例中00 34也就是對應的是jdk1.8,也就是說是由jdk1.8編譯的。
在這裏插入圖片描述
常量池數量(00 3A),轉換爲十進制就是58,也就是說有58個常量,
constant_pool=constant_pool_count-1,本例中也就是常量有57個,我們可以通過javap -v Person.class命令得到如下反編譯之後的結果,可以看到Constant pool是從1到57的

Classfile /E:/project/study/src/main/java/com/sample/study/test/Person.class
  Last modified 2020-5-21; size 911 bytes
  MD5 checksum 934fb0bd52076255f9a7e34b641c3476
  Compiled from "Person.java"
public class com.sample.study.test.Person
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #10.#38        // java/lang/Object."<init>":()V
   #2 = String             #39            // jack
   #3 = Fieldref           #13.#40        // com/sample/study/test/Person.name:Ljava/lang/String;
   #4 = Double             100.0d
   #6 = Fieldref           #13.#41        // com/sample/study/test/Person.salary:D
   #7 = Fieldref           #42.#43        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = String             #44            // person say ...
   #9 = Methodref          #45.#46        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #10 = Class              #47            // java/lang/Object
  #11 = Methodref          #13.#48        // com/sample/study/test/Person.calc:(II)I
  #12 = Fieldref           #13.#49        // com/sample/study/test/Person.obj:Ljava/lang/Object;
  #13 = Class              #50            // com/sample/study/test/Person
  #14 = Utf8               name
  #15 = Utf8               Ljava/lang/String;
  #16 = Utf8               age
  #17 = Utf8               I
  #18 = Utf8               salary
  #19 = Utf8               D
  #20 = Utf8               ConstantValue
  #21 = Utf8               address
  #22 = Utf8               hobby
  #23 = String             #51            // programming
  #24 = Utf8               obj
  #25 = Utf8               Ljava/lang/Object;
  #26 = Utf8               <init>
  #27 = Utf8               ()V
  #28 = Utf8               Code
  #29 = Utf8               LineNumberTable
  #30 = Utf8               say
  #31 = Utf8               calc
  #32 = Utf8               (II)I
  #33 = Utf8               main
  #34 = Utf8               ([Ljava/lang/String;)V
  #35 = Utf8               <clinit>
  #36 = Utf8               SourceFile
  #37 = Utf8               Person.java
  #38 = NameAndType        #26:#27        // "<init>":()V
  #39 = Utf8               jack
  #40 = NameAndType        #14:#15        // name:Ljava/lang/String;
  #41 = NameAndType        #18:#19        // salary:D
  #42 = Class              #52            // java/lang/System
  #43 = NameAndType        #53:#54        // out:Ljava/io/PrintStream;
  #44 = Utf8               person say ...
  #45 = Class              #55            // java/io/PrintStream
  #46 = NameAndType        #56:#57        // println:(Ljava/lang/String;)V
  #47 = Utf8               java/lang/Object
  #48 = NameAndType        #31:#32        // calc:(II)I
  #49 = NameAndType        #24:#25        // obj:Ljava/lang/Object;
  #50 = Utf8               com/sample/study/test/Person
  #51 = Utf8               programming
  #52 = Utf8               java/lang/System
  #53 = Utf8               out
  #54 = Utf8               Ljava/io/PrintStream;
  #55 = Utf8               java/io/PrintStream
  #56 = Utf8               println
  #57 = Utf8               (Ljava/lang/String;)V
{
  public com.sample.study.test.Person();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String jack
         7: putfield      #3                  // Field name:Ljava/lang/String;
        10: aload_0
        11: ldc2_w        #4                  // double 100.0d
        14: putfield      #6                  // Field salary:D
        17: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 6: 10

  public void say();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #8                  // String person say ...
         5: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 11: 0
        line 12: 8

  public static int calc(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=2
         0: iconst_3
         1: istore_0
         2: iload_0
         3: iload_1
         4: iadd
         5: istore_2
         6: new           #10                 // class java/lang/Object
         9: dup
        10: invokespecial #1                  // Method java/lang/Object."<init>":()V
        13: astore_3
        14: iload_2
        15: ireturn
      LineNumberTable:
        line 14: 0
        line 15: 2
        line 16: 6
        line 17: 14

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: iconst_1
         1: iconst_2
         2: invokestatic  #11                 // Method calc:(II)I
         5: pop
         6: return
      LineNumberTable:
        line 20: 0
        line 21: 6

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #10                 // class java/lang/Object
         3: dup
         4: invokespecial #1                  // Method java/lang/Object."<init>":()V
         7: putstatic     #12                 // Field obj:Ljava/lang/Object;
        10: return
      LineNumberTable:
        line 9: 0
}
SourceFile: "Person.java"

access_flags:訪問標誌,主要標記的是接口或者類的信息,接口類型等
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章