JVM虚拟机---(7)Class文件结构之常量池

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq1021979964/article/details/97127467

Class文件结构之常量池

在主次版本号之后的是常量池的入口,常量池可以理解为Class文件中的资源仓库,

它是Class文件结构中与其它项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时还是Class中第一个出现的表类型数据项目。

1.常量池存放的内容

  • 字面量(Literal):
文本字符串、声明为final的常量值。
  • 符号引用(Symbolic References):
类和接口的全限定名(Fully Qualified Name)。

字段的名称和描述符(Descriptor)。

方法的名称和描述符。

 

这14种常量类型各自均有自己的结构

案例

public class TestConstant {
==
    private final int a = 10;
    private final int b = 10;
    private int c = 11;
    private int d = 11;
    private long e = -11111110005514L;
    private long f = -11111110005514L;
    private double g = 10.4557848D;
    private double h = 10.4557848D;
    private String y = "JVM";
    private String j = "JVM";=

}

编译成class文件,使用UltraEdit打开,可以得到Java编译后的字节码

 

第9,10字节是常量池计数器,表示常量池中有54项常量。(37的十进制值是55)。由于常量池容量计数是从1开始,0用作表示“不引用任何对象”,因此,常量个数为54个。

2.获取第一个常量

第11字节是第一个常量的tag,“0A”对应十进制值是10,根据上表得出的常量类型是CONSTANT_Methodref_info。

CONSTANT_Methodref_info的数据结构

  • Tag
表示当前的数据类型CONSTANT_Methodref_info,说明这个常量是一个方法。
  • class_index
表示引用的这个方法的对象在常量池数组的索引,说明constant_pool[class_index]存放的就是调用该方法的对象名称。
  • Name_and_type_index
表示该方法在常量池数据的索引,即constant_pool[name_and_type_index]存放着该方法的名称。

根据数据结构:“12”对应的十进制值是18,“29”对应的十进制值是41。

那么class_index = 18,name_and_type_index = 41。

得出Class_index[18] = java/lang/Object

Name_and_type_index[41] = "<init>":()V

因此,第一个常量constant_pool[1]为java/lang/Object. "<init>":()V

3.获取第二个常量

第二个常量的tag,“09”对应十进制值是09,根据上表得出的常量类型是CONSTANT_Fieldref_info。

CONSTANT_Fieldref_info的数据结构

  • Tag
表示当前的数据类型CONSTANT_Fieldref_info,说明这个常量是一个字段。
  • class_index
表示引用的这个方法的对象在常量池数组的索引,说明constant_pool[class_index]存放的就是调用该方法的对象名称。
  • Name_and_type_index
表示该方法在常量池数据的索引,即constant_pool[name_and_type_index]存放着该方法的名称。

根据数据结构:“12”对应的十进制值是17,“2A”对应的十进制值是42。

那么class_index = 17,name_and_type_index = 42。

得出Class_index[17] = TestConstant

Name_and_type_index[42] = a:I

因此,第二个常量constant_pool[2]为TestConstant.a:I

依次类推进行寻找常量

 

4.通过javap对class文件进行解析

当然,我们也可以通过javap对class文件进行解析。

javap命令使用方法和输入方法结果如下:

javap -verbose TestConstant.class

C:\Users\caonanqing\Desktop>javap -verbose TestConstant.class
Classfile /C:/Users/caonanqing/Desktop/TestConstant.class
  Last modified 2019-7-22; size 619 bytes
  MD5 checksum 5492f3d2a3a963e0a0506757c5fbb22e
  Compiled from "TestConstant.java"
public class TestConstant
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #18.#41        // java/lang/Object."<init>":()V
   #2 = Fieldref           #17.#42        // TestConstant.a:I
   #3 = Fieldref           #17.#43        // TestConstant.b:I
   #4 = Fieldref           #17.#44        // TestConstant.c:I
   #5 = Fieldref           #17.#45        // TestConstant.d:I
   #6 = Long               -11111110005514l
   #8 = Fieldref           #17.#46        // TestConstant.e:J
   #9 = Fieldref           #17.#47        // TestConstant.f:J
  #10 = Double             10.4557848d
  #12 = Fieldref           #17.#48        // TestConstant.g:D
  #13 = Fieldref           #17.#49        // TestConstant.h:D
  #14 = String             #50            // JVM
  #15 = Fieldref           #17.#51        // TestConstant.y:Ljava/lang/String;
  #16 = Fieldref           #17.#52        // TestConstant.j:Ljava/lang/String;
  #17 = Class              #53            // TestConstant
  #18 = Class              #54            // java/lang/Object
  #19 = Utf8               a
  #20 = Utf8               I
  #21 = Utf8               ConstantValue
  #22 = Integer            10
  #23 = Utf8               b
  #24 = Utf8               c
  #25 = Utf8               d
  #26 = Utf8               e
  #27 = Utf8               J
  #28 = Utf8               f
  #29 = Utf8               g
  #30 = Utf8               D
  #31 = Utf8               h
  #32 = Utf8               y
  #33 = Utf8               Ljava/lang/String;
  #34 = Utf8               j
  #35 = Utf8               <init>
  #36 = Utf8               ()V
  #37 = Utf8               Code
  #38 = Utf8               LineNumberTable
  #39 = Utf8               SourceFile
  #40 = Utf8               TestConstant.java
  #41 = NameAndType        #35:#36        // "<init>":()V
  #42 = NameAndType        #19:#20        // a:I
  #43 = NameAndType        #23:#20        // b:I
  #44 = NameAndType        #24:#20        // c:I
  #45 = NameAndType        #25:#20        // d:I
  #46 = NameAndType        #26:#27        // e:J
  #47 = NameAndType        #28:#27        // f:J
  #48 = NameAndType        #29:#30        // g:D
  #49 = NameAndType        #31:#30        // h:D
  #50 = Utf8               JVM
  #51 = NameAndType        #32:#33        // y:Ljava/lang/String;
  #52 = NameAndType        #34:#33        // j:Ljava/lang/String;
  #53 = Utf8               TestConstant
  #54 = Utf8               java/lang/Object
{
  public TestConstant();
    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: bipush        10
         7: putfield      #2                  // Field a:I
        10: aload_0
        11: bipush        10
        13: putfield      #3                  // Field b:I
        16: aload_0
        17: bipush        11
        19: putfield      #4                  // Field c:I
        22: aload_0
        23: bipush        11
        25: putfield      #5                  // Field d:I
        28: aload_0
        29: ldc2_w        #6                  // long -11111110005514l
        32: putfield      #8                  // Field e:J
        35: aload_0
        36: ldc2_w        #6                  // long -11111110005514l
        39: putfield      #9                  // Field f:J
        42: aload_0
        43: ldc2_w        #10                 // double 10.4557848d
        46: putfield      #12                 // Field g:D
        49: aload_0
        50: ldc2_w        #10                 // double 10.4557848d
        53: putfield      #13                 // Field h:D
        56: aload_0
        57: ldc           #14                 // String JVM
        59: putfield      #15                 // Field y:Ljava/lang/String;
        62: aload_0
        63: ldc           #14                 // String JVM
        65: putfield      #16                 // Field j:Ljava/lang/String;
        68: return
      LineNumberTable:
        line 1: 0
        line 3: 4
        line 4: 10
        line 5: 16
        line 6: 22
        line 7: 28
        line 8: 35
        line 9: 42
        line 10: 49
        line 11: 56
        line 12: 62
}
SourceFile: "TestConstant.java"

常量池的结束,人工手动找很麻烦,可以直接用javap -verbose TestConstant.class命令找到。

根据得到常量池结束时Object,那么对应字节码得到是在74.

猜你喜欢

转载自blog.csdn.net/qq1021979964/article/details/97127467