Java class文件格式之?dāng)?shù)據(jù)類型_動力節(jié)點Java學(xué)院整理
CONSTANT_Integer_info
一個常量池中的CONSTANT_Integer_info數(shù)據(jù)項, 可以看做是CONSTANT_Integer類型的一個實例。 它存儲的是源文件中出現(xiàn)的int型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個字節(jié)也是一個tag值, 它的tag值為3, 也就是說, 當(dāng)虛擬機(jī)讀到一個tag值為3的數(shù)據(jù)項時, 就知道這個數(shù)據(jù)項是一個CONSTANT_Integer_info, 它存儲的是int型數(shù)值的值。 緊挨著tag的下面4個字節(jié)叫做bytes, 就是int型數(shù)值的整型值。 它的內(nèi)存布局如下:

下面以示例代碼進(jìn)行說明, 示例代碼如下:
package com.bjpowernode.test;
public class TestInt {
void printInt(){
System.out.println(65535);
}
}
將上面的類生成的class文件反編譯:
1.D:\Workspace\AndroidWorkspace\BlogTest\bin>javap -v -c -classpath . com.bjpowernode.test.TestInt
下面列出反編譯的結(jié)果, 由于反編譯結(jié)果較長, 我們省略了大部分信息:
..................
..................
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/bjpowernode/test/TestInt;
}
上面的輸出結(jié)果中, 保留了printInt方法的反編譯結(jié)果, 并且保留了常量池中的第21項。 首先看printInt方法反編譯結(jié)果中的索引為3 的字節(jié)碼指令:
1.3: ldc #21 // int 65535
這條ldc指令, 引用了常量池中的第21項, 而第21項是一個CONSTANT_Integer_info, 并且這個CONSTANT_Integer_info存儲的整型值為65535 。
CONSTANT_Float_info
一個常量池中的CONSTANT_Float_info數(shù)據(jù)項, 可以看做是CONSTANT_Float類型的一個實例。 它存儲的是源文件中出現(xiàn)的float型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個字節(jié)也是一個tag值, 它的tag值為4, 也就是說, 當(dāng)虛擬機(jī)讀到一個tag值為4的數(shù)據(jù)項時, 就知道這個數(shù)據(jù)項是一個CONSTANT_Float_info, 并且知道它存儲的是float型數(shù)值。 緊挨著tag的下面4個字節(jié)叫做bytes, 就是float型的數(shù)值。 它的內(nèi)存布局如下:

舉例說明, 如果源文件中的一句代碼使用了一個float值, 如下所示:
void printFloat(){
System.out.println(1234.5f);
}
那么在這個類的常量池中就會有一個CONSTANT_Float_info與之相對應(yīng), 這個CONSTANT_Float_info的形式如下:

代碼反編譯結(jié)果如下:
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/bjpowernode/test/TestInt;
}
CONSTANT_Long_info
一個常量池中的CONSTANT_Long_info數(shù)據(jù)項, 可以看做是CONSTANT_Long類型的一個實例。 它存儲的是源文件中出現(xiàn)的long型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個字節(jié)也是一個tag值, 它的tag值為5, 也就是說, 當(dāng)虛擬機(jī)讀到一個tag值為5的數(shù)據(jù)項時, 就知道這個數(shù)據(jù)項是一個CONSTANT_Long_info, 并且知道它存儲的是long型數(shù)值。 緊挨著tag的下面8個字節(jié)叫做bytes, 就是long型的數(shù)值。 它的內(nèi)存布局如下:

舉例說明, 如果源文件中的一句代碼使用了一個long型的數(shù)值, 如下所示:
void printLong(){
System.out.println(123456L);
}
那么在這個類的常量池中就會有一個CONSTANT_Long_info與之相對應(yīng), 這個CONSTANT_Long_info的形式如下:

代碼反編譯結(jié)果為:
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/bjpowernode/test/TestInt;
}
CONSTANT_Double_info
一個常量池中的CONSTANT_Double_info數(shù)據(jù)項, 可以看做是CONSTANT_Double類型的一個實例。 它存儲的是源文件中出現(xiàn)的double型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個字節(jié)也是一個tag值, 它的tag值為6, 也就是說, 當(dāng)虛擬機(jī)讀到一個tag值為6的數(shù)據(jù)項時, 就知道這個數(shù)據(jù)項是一個CONSTANT_Double_info, 并且知道它存儲的是double型數(shù)值。 緊挨著tag的下面8個字節(jié)叫做bytes, 就是double型的數(shù)值。 它的內(nèi)存布局如下:

舉例說明, 如果源文件中的一句代碼使用了一個double型的數(shù)值, 如下所示:
void printDouble(){
System.out.println(123456D);
}
那么在這個類的常量池中就會有一個CONSTANT_Double_info與之相對應(yīng), 這個CONSTANT_Double_info的形式如下:

代碼反編譯結(jié)果為:
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/bjpowernode/test/TestInt;
}
CONSTANT_String_info
在常量池中, 一個CONSTANT_String_info數(shù)據(jù)項, 是CONSTANT_String類型的一個實例。 它的作用是存儲文字字符串, 可以把他看做是一個存在于class文件中的字符串對象。 同樣, 它的第一個字節(jié)是tag值, 值為8 , 也就是說, 虛擬機(jī)訪問一個數(shù)據(jù)項時, 判斷tag值為8 , 就說明訪問的數(shù)據(jù)項是一個CONSTANT_String_info 。 緊挨著tag的后兩個字節(jié)是一個叫做string_index的常量池引用, 它指向一個CONSTANT_Utf8_info, 這個CONSTANT_Utf8_info存放的才是字符串的字面量。 它的內(nèi)存布局如下:

舉例說明, 如果源文件中的一句代碼使用了一個字符串常量, 如下所示:
void printStrng(){
System.out.println("abcdef");
}
那么在這個類的常量池中就會有一個CONSTANT_String_info與之相對應(yīng), 反編譯結(jié)果如下:
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/bjpowernode/test/TestInt;
}
其中printString方法中索引為3的字節(jié)碼指令ldc引用常量池中的第21項, 第21項是一個CONSTANT_String_info, 這個位于第21項的CONSTANT_String_info又引用了常量池的第22項, 第22項是一個CONSTANT_Utf8_info, 這個CONSTANT_Utf8_info中存儲的字符串是 abcdef 。 引用關(guān)系的內(nèi)存布局如下:

總結(jié)
最后總結(jié)一下, 本文主要講解了常量池中的五中數(shù)據(jù)項, 分別為CONSTANT_Integer_info, CONSTANT_Float_info, CONSTANT_Long_info, CONSTANT_Double_info 和CONSTANT_String_info 。 這幾種常量池數(shù)據(jù)項都是直接存儲的常量值,而不是符號引用。 這里又一次出現(xiàn)了符號引用的概念, 這個概念將會在下一篇博客中詳細(xì)講解, 因為下一篇博客要介紹的剩下的四種常量池數(shù)據(jù)項, 都是符號引用, 這四種表示符號引用的數(shù)據(jù)項又會直接或間接引用上篇文章中介紹的CONSTANT_NameAndType_info和CONSTANT_Utf8_info, 所以說CONSTANT_NameAndType_info是符號引用的一部分。
從本文中我們還可以知道。 雖然說CONSTANT_String_info是直接存儲值的數(shù)據(jù)項, 但是CONSTANT_String_info有點特別, 因為它不是直接存儲字符串, 而是引用了一個CONSTANT_Utf8_info, 這個被引用的CONSTANT_Utf8_info中存儲了字符串。
- Java class文件格式總結(jié)_動力節(jié)點Java學(xué)院整理
- Java class文件格式之特殊字符串_動力節(jié)點Java學(xué)院整理
- Java class文件格式之?dāng)?shù)據(jù)類型(二)_動力節(jié)點Java學(xué)院整理
- Java class文件格式之方法_動力節(jié)點Java學(xué)院整理
- Java class文件格式之屬性_動力節(jié)點Java學(xué)院整理
- Java class文件格式之常量池_動力節(jié)點Java學(xué)院整理
- Java class文件格式之訪問標(biāo)志信息_動力節(jié)點Java學(xué)院整理
- Java class文件格式之屬性詳解_動力節(jié)點java學(xué)院整理
- 深入理解Java class文件格式_動力節(jié)點Java學(xué)院整理
相關(guān)文章
java使用篩選法求n以內(nèi)的素數(shù)示例(java求素數(shù))
這篇文章主要介紹了java使用篩選法求n以內(nèi)的素數(shù)示例(java求素數(shù)),需要的朋友可以參考下2014-04-04
淺談Java中浮點型數(shù)據(jù)保留兩位小數(shù)的四種方法
今天在進(jìn)行開發(fā)的過程中遇到了一個小問題,是關(guān)于如何將double類型的數(shù)據(jù)保留兩位小數(shù)。具有一定的參考價值,本文就詳細(xì)的介紹一下2021-09-09
SpringSecurity實現(xiàn)圖形驗證碼功能的實例代碼
Spring Security 的前身是 Acegi Security ,是 Spring 項目組中用來提供安全認(rèn)證服務(wù)的框架。這篇文章主要介紹了SpringSecurity實現(xiàn)圖形驗證碼功能,需要的朋友可以參考下2018-10-10
java代碼獲取數(shù)據(jù)庫表里數(shù)據(jù)的總數(shù)操作
這篇文章主要介紹了java代碼獲取數(shù)據(jù)庫表里數(shù)據(jù)的總數(shù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08

