Class

现在开始讲解class文件解析。class文件就是一个数据结构,跟elf文件类似。

class文件的15个部分:

image-20250508224518601

1.Magic Number 魔數

2.Version 版本號

3.Constant Pool Count 常量池數量 2个字节,16位故常量最多2^16^ =65,536 个

4.Constant Pool 常量池

5.Access Flags 訪問標誌

6.Class Name 類別名稱

7.Super Class Name 父類別名稱

8.Interfaces Count 接口的數量 = 0001:1个接口

9.Interfaces 接口 = 0005:常量池第5个索引

10.Fields Count 字段的數量 = 0001:1个字段

11.Fields 字段

12.Methods Count 方法的數量

13.Methods 方法

方法与字段的结构:

image-20250506114303426

其中descriptor_index描述了参数类型与返回类型

14.Attributes Count 屬性的數量

15.Attributes 屬性

终极杀器:javap -verbose a.class

https://www.jyt0532.com/2020/03/01/class-file-structure/

public class demo {

    int a = 1;

    static int b = 2;

    static final int c = 3;

    final int d = 4;

    String e = "ee";

    public static void main(String[] args) {
        System.out.println(b);
    }
}
liaozk@mac-air jvm % javap -verbose demo
Classfile /Users/liaozk/Documents/Foundation/jvm/out/production/jvm/demo.class
  Last modified 2025年5月6日; size 739 bytes
  SHA-256 checksum 401ff86cf6fc738b07c81d15def8b323ae0c425787457ea2d5637a84319ae113
  Compiled from "demo.java"
public class demo
  minor version: 0
  major version: 61
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // demo
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 5, methods: 3, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // demo.a:I
   #8 = Class              #10            // demo
   #9 = NameAndType        #11:#12        // a:I
  #10 = Utf8               demo
  #11 = Utf8               a
  #12 = Utf8               I
  #13 = Fieldref           #8.#14         // demo.d:I
  #14 = NameAndType        #15:#12        // d:I
  #15 = Utf8               d
  #16 = String             #17            // ee
  #17 = Utf8               ee
  #18 = Fieldref           #8.#19         // demo.e:Ljava/lang/String;
  #19 = NameAndType        #20:#21        // e:Ljava/lang/String;
  #20 = Utf8               e
  #21 = Utf8               Ljava/lang/String;
  #22 = Fieldref           #23.#24        // java/lang/System.out:Ljava/io/PrintStream;
  #23 = Class              #25            // java/lang/System
  #24 = NameAndType        #26:#27        // out:Ljava/io/PrintStream;
  #25 = Utf8               java/lang/System
  #26 = Utf8               out
  #27 = Utf8               Ljava/io/PrintStream;
  #28 = Fieldref           #8.#29         // demo.b:I
  #29 = NameAndType        #30:#12        // b:I
  #30 = Utf8               b
  #31 = Methodref          #32.#33        // java/io/PrintStream.println:(I)V
  #32 = Class              #34            // java/io/PrintStream
  #33 = NameAndType        #35:#36        // println:(I)V
  #34 = Utf8               java/io/PrintStream
  #35 = Utf8               println
  #36 = Utf8               (I)V
  #37 = Utf8               c
  #38 = Utf8               ConstantValue
  #39 = Integer            3
  #40 = Integer            4
  #41 = Utf8               Code
  #42 = Utf8               LineNumberTable
  #43 = Utf8               LocalVariableTable
  #44 = Utf8               this
  #45 = Utf8               Ldemo;
  #46 = Utf8               main
  #47 = Utf8               ([Ljava/lang/String;)V
  #48 = Utf8               args
  #49 = Utf8               [Ljava/lang/String;
  #50 = Utf8               <clinit>
  #51 = Utf8               SourceFile
  #52 = Utf8               demo.java
{
  int a;
    descriptor: I
    flags: (0x0000)

  static int b;
    descriptor: I
    flags: (0x0008) ACC_STATIC

  static final int c;
    descriptor: I
    flags: (0x0018) ACC_STATIC, ACC_FINAL
    ConstantValue: int 3

  final int d;
    descriptor: I
    flags: (0x0010) ACC_FINAL
    ConstantValue: int 4

  java.lang.String e;
    descriptor: Ljava/lang/String;
    flags: (0x0000)

  public demo();
    descriptor: ()V
    flags: (0x0001) 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: iconst_1
         6: putfield      #7                  // Field a:I
         9: aload_0
        10: iconst_4
        11: putfield      #13                 // Field d:I
        14: aload_0
        15: ldc           #16                 // String ee
        17: putfield      #18                 // Field e:Ljava/lang/String;
        20: return
      LineNumberTable:
        line 1: 0
        line 3: 4
        line 9: 9
        line 11: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  this   Ldemo;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #22                 // Field java/lang/System.out:Ljava/io/PrintStream;
         3: getstatic     #28                 // Field b:I
         6: invokevirtual #31                 // Method java/io/PrintStream.println:(I)V
         9: return
      LineNumberTable:
        line 14: 0
        line 15: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  args   [Ljava/lang/String;

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_2
         1: putstatic     #28                 // Field b:I
         4: return
      LineNumberTable:
        line 5: 0
}
SourceFile: "demo.java"
liaozk@mac-air jvm %