举例说明, 如果源文件中的一句代码使用了一个long型的数值, 如下所示:
void printLong(){
System.out.println(123456L);
}
那么在这个类的常量池中就会有一个CONSTANT_Long_info与之相对应, 这个CONSTANT_Long_info的形式如下:
代码反编译结果为:
Constant pool:
..............
..............
#21 = Long 123456l
..............
..............
{
..............
..............
void printLong();
flags:
Code:
stack=3, locals=1, args_size=1
0: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc2_w #21 // long 123456l
6: invokevirtual #23 // Method java/io/PrintStream.println:(J)V
9: return
LineNumberTable:
line 7: 0
line 8: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/jg/zhang/TestInt;
}
(6)CONSTANT_Double_info
一个常量池中的CONSTANT_Double_info数据项, 可以看做是CONSTANT_Double类型的一个实例。 它存储的是源文件中出现的double型数据的值。 同样, 作为常量池中的一种数据类型, 它的第一个字节也是一个tag值, 它的tag值为6, 也就是说, 当虚拟机读到一个tag值为6的数据项时, 就知道这个数据项是一个CONSTANT_Double_info, 并且知道它存储的是double型数值。 紧挨着tag的下面8个字节叫做bytes, 就是double型的数值。 它的内存布局如下:
举例说明, 如果源文件中的一句代码使用了一个double型的数值, 如下所示:
void printDouble(){
System.out.println(123456D);
}
那么在这个类的常量池中就会有一个CONSTANT_Double_info与之相对应, 这个CONSTANT_Double_info的形式如下:
Constant pool:
..............
..............
#21 = Double 123456.0d
..............
..............
{
..............
..............
void printDouble();
flags:
Code:
stack=3, locals=1, args_size=1
0: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc2_w #21 // double 123456.0d
6: invokevirtual #23 // Method java/io/PrintStream.println:(D)V
9: return
LineNumberTable:
line 7: 0
line 8: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/jg/zhang/TestInt;
}
(7) CONSTANT_String_info
在常量池中, 一个CONSTANT_String_info数据项, 是CONSTANT_String类型的一个实例。 它的作用是存储文字字符串, 可以把他看做是一个存在于class文件中的字符串对象。 同样, 它的第一个字节是tag值, 值为8 , 也就是说, 虚拟机访问一个数据项时, 判断tag值为8 , 就说明访问的数据项是一个CONSTANT_String_info 。 紧挨着tag的后两个字节是一个叫做string_index的常量池引用, 它指向一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info存放的才是字符串的字面量。 它的内存布局如下:
举例说明, 如果源文件中的一句代码使用了一个字符串常量, 如下所示:
void printStrng(){
System.out.println("abcdef");
}
那么在这个类的常量池中就会有一个CONSTANT_String_info与之相对应, 反编译结果如下:
Constant pool:
..............
..............
#21 = String #22 // abcdef
#22 = Utf8 abcdef
..............
..............
{
..............
..............
void printStrng();
flags:
Code:
stack=2, locals=1, args_size=1
0: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #21 // String abcdef
5: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 7: 0
line 8: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/jg/zhang/TestInt;
}
其中printString方法中索引为3的字节码指令ldc引用常量池中的第21项, 第21项是一个CONSTANT_String_info, 这个位于第21项的CONSTANT_String_info又引用了常量池的第22项, 第22项是一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info中存储的字符串是 abcdef 。 引用关系的内存布局如下:
总结
本文就到此为止。 最后总结一下, 本文主要讲解了常量池中的五中数据项, 分别为CONSTANT_Integer_info, CONSTANT_Float_info, CONSTANT_Long_info, CONSTANT_Double_info 和CONS