Jvm学习笔记(二)

Class类文件结构


Jvm学习笔记(二)_第1张图片
Class类文件结构
  • 无符号数:u1、u2、u4、u8分别代表1个字节、2个字节、4个字节、8个字节

  • magic:魔数,4个字节,唯一取值"0xCAFEBABE"

  • minjor_version、major_version:Class文件版本号

  • constant_pool_count:由于常量池数量不固定,在常量池入口放置一2字节类型数据,代表常量池容量计数。计数从1开始。即constant_pool_count = constant_pool长度+1 。

  • constant_pool:常量池。包括字面量和符号引用。字面量指java中的字符串和final类型常量等。符号引用包括类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。

Jvm学习笔记(二)_第2张图片
常量池标志位

CONSTANT_Class_info结构里包含一个name_index,指向一个 CONSTANT_Utf8_info,为这个类的全限定名。CONSTANT_Utf8_info结构包含length,和bytes。

CONSTANT_Class_info {
    u1 tag;   //tag取值为7,代表CONSTANT_Class_info
    u2 name_index;  //name_index表示代表自己类名的字符串信息位于于常量池数组中哪一个,也就是索引
}
CONSTANT_Utf8_info {
    u1 tag;
    u2 length;  //下面就是存储UTF8字符串的地方了
    u1 bytes[length];
}
CONSTANT_NameAndType_info {
   u1 tag;
   u2 name_index;  //方法名或域名对应的字符串索引
   u2 descriptor_index; //方法信息(参数+返回值),或者成员变量的信息(类型)对应的字符串索引
}
CONSTANT_Fieldref_info {
   u1 tag;
   u2 class_index;  
   u2 name_and_type_index; 
}
CONSTANT_Methodref_info {
   u1 tag;
   u2 class_index;  
   u2 name_and_type_index;
}
CONSTANT_InterfaceMethodref_info {
   u1 tag;
   u2 class_index;  
   u2 name_and_type_index; 
}
  • access_flags:标志位。包括:这个 Class 是类还是接口,是否定义为 public 类型,abstract 类型,如果是类的话,是否声明为 final,等等。

  • this_class、super_class:类索引、父类索引。

  • interfaces、fields、methods:接口、变量、方法。

  • attributes:属性表。


示例:

public class TestMain{
    public int x = 0;

    public static void main (String [] args){
        TestMain testMain = new TestMain();
        testMain.test();
    }

    public TestMain(){

    }
    public void test(){
        
    }
}

javap -verbose

public class TestMain                                                                 
  minor version: 0                                                                    
  major version: 52                                                                   
  flags: ACC_PUBLIC, ACC_SUPER                                                        
Constant pool:                                                                        
   #1 = Class              #18            // TestMain                                 
   #2 = Methodref          #1.#19         // TestMain."":()V                    
   #3 = Methodref          #1.#20         // TestMain.test:()V                        
   #4 = Methodref          #6.#19         // java/lang/Object."":()V            
   #5 = Fieldref           #1.#21         // TestMain.x:I                             
   #6 = Class              #22            // java/lang/Object                         
   #7 = Utf8               x                                                          
   #8 = Utf8               I                                                          
   #9 = Utf8               main                                                       
  #10 = Utf8               ([Ljava/lang/String;)V                                     
  #11 = Utf8               Code                                                       
  #12 = Utf8               LineNumberTable                                            
  #13 = Utf8                                                                    
  #14 = Utf8               ()V                                                        
  #15 = Utf8               test                                                       
  #16 = Utf8               SourceFile                                                 
  #17 = Utf8               TestMain.java                                              
  #18 = Utf8               TestMain                                                   
  #19 = NameAndType        #13:#14        // "":()V                             
  #20 = NameAndType        #15:#14        // test:()V                                 
  #21 = NameAndType        #7:#8          // x:I                                      
  #22 = Utf8               java/lang/Object                                           
{                                                                                     
  public int x;                                                                       
    descriptor: I                                                                     
    flags: ACC_PUBLIC                                                                 
                                                                                      
  public static void main(java.lang.String[]);                                        
    descriptor: ([Ljava/lang/String;)V                                                
    flags: ACC_PUBLIC, ACC_STATIC                                                     
    Code:                                                                             
      stack=2, locals=2, args_size=1                                                  
         0: new           #1                  // class TestMain                       
         3: dup                                                                       
         4: invokespecial #2                  // Method "":()V                  
         7: astore_1                                                                  
         8: aload_1                                                                   
         9: invokevirtual #3                  // Method test:()V                      
        12: return                                                                    
      LineNumberTable:                                                                
        line 5: 0                                                                     
        line 6: 8                                                                     
        line 7: 12                                                                    
                                                                                      
  public TestMain();                                                                  
    descriptor: ()V                                                                   
    flags: ACC_PUBLIC                                                                 
    Code:                                                                             
      stack=2, locals=1, args_size=1                                                  
         0: aload_0                                                                   
         1: invokespecial #4                  // Method java/lang/Object."":()V 
         4: aload_0                                                                   
         5: iconst_0                                                                  
         6: putfield      #5                  // Field x:I                            
         9: return                                                                    
      LineNumberTable:                                                                
        line 9: 0                                                                     
        line 2: 4                                                                     
        line 11: 9                                                                    
                                                                                      
  public void test();                                                                 
    descriptor: ()V                                                                   
    flags: ACC_PUBLIC                                                                 
    Code:                                                                             
      stack=0, locals=1, args_size=1                                                  
         0: return                                                                    
      LineNumberTable:                                                                
        line 14: 0                                                                    
}                                                                                     
SourceFile: "TestMain.java"                                                           
                                                                                      
  • 如上,在常量池中,第一个元素为Class,即CONSTANT_Class_info,它的name_index为第18个元素,即Utf8_info,内容为字符串"TestMain"。第二个元素为Methodref_info,其class_index为第一个元素,即"TestMain",name_and_type_index为第19个元素,对应第13个元素和第14个元素,V代表void。以此类推。

  • Code属性:

    • stack=2,locals=2,args_size=1。结合代码,main函数确实有一个参数,而且还有一个本地变量。注意,main函数是static的。如果对于类的非static函数,那么locals的第0个元素代表this。stack表示操作数最大栈深度。locals表示局部变量所需要的空间,以slot为单位。args_size参数个数。
    • stack后面接下来的就是code数组,也就是这个函数对应的执行代码。0表示code[]的索引位置。0:new:代表这个操作是new操作,此操作对应的字节码长度为3,所以下一个操作对应的字节码从索引3开始。
    • LineNumberTable:也是属性的一种,用于调试,它将源码和字节码匹配了起来。比如line 5: 0这句话代表该函数字节码0那一个操作对应代码的第5行。

你可能感兴趣的:(Jvm学习笔记(二))