JVM互联网科技程序员

Class文件结构--常量池(一)

2017-04-08  本文已影响517人  zlcook

前言

Class类文件的结构

全局规范

package com.zlcook.clazz;

public class TestClass{
  private int m;
  public int inc(){
   return m+1;
  }
}

1. 魔数与Class文件的版本

TestClass.class文件的前8个字节

2. 常量池

2.1 常量池中存放的内容

2.2 常量池中为什么要包含这些内容

2.3 Class文件中如何描述常量池中内容

类型 名称 数量
u2(无符号数) constant_pool_count 1
cp_info(表) constant_pool constant_pool_count-1

2.3.1 constant_pool_count

TestClass.class文件中constant_pool_count的十进制值为19

2.3.2 constant_pool

14种常量项结构
占用字节
CONSTANT_Class_info 3
CONSTANT_Integer_info 5
CONSTANT_Fieldref_info 5
CONSTANT_Methodref_info 5
CONSTANT_Utf8_info 不固定,取决于length大小

2.4 查找testClass.class文件的第一个常量项内容

第一个表的tag为10 Paste_Image.png 第二个常量项

根据CONSTANT_Class_info项常量项的结构可知其index数据项又是一个索引项,指向全限定名常量项索引,index数据项的值为0X12=18,表示指向第18个常量项,根据constant_pool_count的值为19可得,常量池中一共有18个常量项,巧了正好在最后一个,但是要知道18个常量项必须知道前17个常量项所占字节,这里就不一一找了,最后找到第18个常量项CONSTANT_Utf8_info在class文件中包含的内容如下:

第18个常量项

到此为止,我们得到了第一个常量项CONSTANT_Methodref_info的第二个数据项index指向的内容为CONSTANT_Class_info常量项,CONSTANT_Class_info常量的第二个数据项index指向CONSTANT_Utf8_info常量项,CONSTANT_Utf8_info常量项的内容为 java/lang/Object 。
当然CONSTANT_Methodref_info常量项还有第三个数据项index,其存放的也是一个其他常量的索引。

2.5 采用javap命令分析class文件

$ javap -verbose TestClass.class
Classfile /E:/studytry/com/zlcook/clazz/TestClass.class
  Last modified 2017-4-7; size 292 bytes
  MD5 checksum 486567c6d4d7432fc359230fed9c92c7
  Compiled from "TestClass.java"
public class com.zlcook.clazz.TestClass
  SourceFile: "TestClass.java"
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#15         //  java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#16         //  com/zlcook/clazz/TestClass.m:I
   #3 = Class              #17            //  com/zlcook/clazz/TestClass
   #4 = Class              #18            //  java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               inc
  #12 = Utf8               ()I
  #13 = Utf8               SourceFile
  #14 = Utf8               TestClass.java
  #15 = NameAndType        #7:#8          //  "<init>":()V
  #16 = NameAndType        #5:#6          //  m:I
  #17 = Utf8               com/zlcook/clazz/TestClass
  #18 = Utf8               java/lang/Object
{
  public com.zlcook.clazz.TestClass();
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0

  public int inc();
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 6: 0
}
 #1 = Methodref          #4.#15       //  java/lang/Object."<init>":()V
第一个常量项 第几个 tag index index 最终代表的内容
class中16进制值 0X0A 0X004 0X000F
转换成10进制值 10 4 15 查完4和15才知道
javap分析显示的友好值 #1 Methodref #4 #15 java/lang/Object."<init>":()V

2.6 class文件中包含的内容

package com.zlcook.clazz;

public class TestClass{
  private int m;
  public int inc(){
   return m+1;
  }
}
Constant pool:
   #1 = Methodref          #4.#15         //  java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#16         //  com/zlcook/clazz/TestClass.m:I
   #3 = Class              #17            //  com/zlcook/clazz/TestClass
   #4 = Class              #18            //  java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               inc
  #12 = Utf8               ()I
  #13 = Utf8               SourceFile
  #14 = Utf8               TestClass.java
  #15 = NameAndType        #7:#8          //  "<init>":()V
  #16 = NameAndType        #5:#6          //  m:I
  #17 = Utf8               com/zlcook/clazz/TestClass
  #18 = Utf8               java/lang/Object

3. 哪些字面量会进入常量池中

8种基本类型:

测试案例:

public class FinalTest{

   private final int int_num =12;
   private final char char_num = 'a';
   private final short short_num =30;
   private final float float_num = 45.3f;
   private final double double_num =39.8;
   private final byte byte_num =121;
   private final long long_num = 2323L;
   private final boolean boolean_flage = true;
}

public class test{

   private int int_num =12;
   private char char_num = 'a';
   private short short_num =30;
   private float float_num = 45.3f;
   private double double_num =39.8;
   private byte byte_num =121;
   private long long_num = 2323L;
   private long long_delay_num ;
   private boolean boolean_flage = true;

   public void init(){
     this.long_delay_num = 5555L;
   }
}

上面代码测试结果:

String类型

public class StringTest{

      private String str1 = "zl"+"cook";
      private String str2 = str1+"hello";
      private String str3 = new String("zlcook here?");
      private String str4 = "everybody "+ new String("here?");

      private final String fin1 = "boy";
      private final String fin2 = fin1+ "is boy";
      private final String fin3 = str1+ "is boy";
}

所有测试数据github: 测试数据

结束

上一篇 下一篇

猜你喜欢

热点阅读