前情回顾
在上一篇博客深入理解Java Class文件格式(三) 中, 介绍了常量池中的两种类型的数据项, 分别是CONSTANT_Utf8_info和CONSTANT_NameAndType_info 。 CONSTANT_Utf8_info中存储了几乎所有类型的字符串, 包括方法名, 字段名, 描述符等等。 而CONSTANT_NameAndType_info是方法符号引用或字段的符号引用的一部分, 也就是说, 如果在源文件中调用了一个方法, 或者引用了一个字段(不管是本类中的方法和字段, 还是引用其他类中的方法和字段), 那么和这个方法或在字段相对应的CONSTANT_NameAndType_info 就会出现在常量池中。 注意, 只有引用了一个方法或字段, 常量池中才会存在和它对应的CONSTANT_NameAndType_info , 如果只在当前类中定义了一个字段而不访问它, 或者定义了一个方法而不调用它, 那么常量池中就不会出现对应的CONSTANT_NameAndType_info 数据项。 CONSTANT_NameAndType_info 中引用了两个CONSTANT_Utf8_info, 一个叫做name_index, 存储方法名或字段名, 一个叫做descriptor_index, 存储方法描述符或字段描述符。
关于这两种常量池数据项的详细介绍, 请参阅上一篇博客:深入理解Java Class文件格式(三) 。 关于 虚拟机和class文件格式的前几篇文章,已经收录在我的博客专栏中, 如果想全面了解这些知识,建议按顺序 阅读我的专栏中的博客, 专栏地址:http://blog.csdn.net/column/details/zhangjg-java-blog.html 。 后续关于深入理解java的其他一些文章, 也会收录在本专栏中, 欢迎关注和交流。
下面我们继续详细讲解常量池中的其他类型的数据项, 本文接着前几篇文章写的, 建议先读前几篇文章。
常量池中各数据项类型详解(续)
(3)CONSTANT_Integer_info
一个常量池中的CONSTANT_Integer_info数据项, 可以看做是CONSTANT_Integer类型的一个实例。 它存储的是源文件中出现的int型数据的值。 同样, 作为常量池中的一种数据类型, 它的第一个字节也是一个tag值, 它的tag值为3, 也就是说, 当虚拟机读到一个tag值为3的数据项时, 就知道这个数据项是一个CONSTANT_Integer_info, 它存储的是int型数值的值。 紧挨着tag的下面4个字节叫做bytes, 就是int型数值的整型值。 它的内存布局如下:
下面以示例代码进行说明, 示例代码如下:
package com.jg.zhang;
public class TestInt {
void printInt(){
System.out.println(65535);
}
}
将上面的类生成的class文件反编译:
D:\Workspace\AndroidWorkspace\BlogTest\bin>javap -v -c -classpath . com.jg.zhang.TestInt
下面列出反编译的结果, 由于反编译结果较长, 我们省略了大部分信息:
..................
..................
Constant pool:
..................
..................
#21 = Integer 65535
..................
..................
{
..................
..................
void printInt();
flags:
Code:
stack=2, locals=1, args_size=1
0: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #21 // int 65535
5: invokevirtual #22 // Method java/io/PrintStream.println:(I)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/jg/zhang/TestInt;
}
3: ldc #21 // int 65535
这条ldc指令, 引用了常量池中的第21项, 而第21项是一个CONSTANT_Integer_info, 并且这个CONSTANT_Integer_info存储的整型值为65535 。
(4)CONSTANT_Float_info
一个常量池中的CONSTANT_Float_info数据项, 可以看做是CONSTANT_Float类型的一个实例。 它存储的是源文件中出现的float型数据的值。 同样, 作为常量池中的一种数据类型, 它的第一个字节也是一个tag值, 它的tag值为4, 也就是说, 当虚拟机读到一个tag值为4的数据项时, 就知道这个数据项是一个CONSTANT_Float_info, 并且知道它存储的是float型数值。 紧挨着tag的下面4个字节叫做bytes, 就是float型的数值。 它的内存布局如下:
举例说明, 如果源文件中的一句代码使用了一个float值, 如下所示:
void printFloat(){
System.out.println(1234.5f);
}
那么在这个类的常量池中就会有一个CONSTANT_Float_info与之相对应, 这个CONSTANT_Float_info的形式如下:
代码反编译结果如下:
Constant pool:
.............
.............
#29 = Float 1234.5f
............
............
{
............
............
void printFloat();
flags:
Code:
stack=2, locals=1, args_size=1
0: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #29 // float 1234.5f
5: invokevirtual #30 // Method java/io/PrintStream.println:(F)V
8: return
LineNumberTable:
line 10: 0
line 11: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/jg/zhang/TestInt;
}
(5)CONSTANT_Long_info
一个常量池中的CONSTANT_Long_info数据项, 可以看做是