日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

深入理解 JVM Class文件格式(四)

發(fā)布時(shí)間:2023/12/4 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解 JVM Class文件格式(四) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

(3)CONSTANT_Integer_info

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


下面以示例代碼進(jìn)行說(shuō)明, 示例代碼如下:

package com.jg.zhang;public class TestInt {void printInt(){System.out.println(65535);} }

將上面的類生成的class文件反編譯,由于反編譯結(jié)果較長(zhǎng), 我們省略了大部分信息:

Constant pool:....................................#21 = Integer 65535....................................{....................................void printInt();flags:Code:stack=2, locals=1, args_size=10: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #21 // int 655355: invokevirtual #22 // Method java/io/PrintStream.println:(I)V8: returnLineNumberTable:line 6: 0line 7: 8LocalVariableTable:Start Length Slot Name Signature0 9 0 this Lcom/jg/zhang/TestInt; }

上面的輸出結(jié)果中, 保留了printInt方法的反編譯結(jié)果, 并且保留了常量池中的第21項(xiàng)。 首先看printInt方法反編譯結(jié)果中的索引為3 的字節(jié)碼指令:

3: ldc #21 // int 65535

這條ldc指令, 引用了常量池中的第21項(xiàng), 而第21項(xiàng)是一個(gè)CONSTANT_Integer_info, 并且這個(gè)CONSTANT_Integer_info存儲(chǔ)的整型值為65535 。

(4)CONSTANT_Float_info

一個(gè)常量池中的CONSTANT_Float_info數(shù)據(jù)項(xiàng), 可以看做是CONSTANT_Float類型的一個(gè)實(shí)例。 它存儲(chǔ)的是源文件中出現(xiàn)的float型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個(gè)字節(jié)也是一個(gè)tag值, 它的tag值為4, 也就是說(shuō), 當(dāng)虛擬機(jī)讀到一個(gè)tag值為4的數(shù)據(jù)項(xiàng)時(shí), 就知道這個(gè)數(shù)據(jù)項(xiàng)是一個(gè)CONSTANT_Float_info, 并且知道它存儲(chǔ)的是float型數(shù)值。 緊挨著tag的下面4個(gè)字節(jié)叫做bytes, 就是float型的數(shù)值。 它的內(nèi)存布局如下:

舉例說(shuō)明, 如果源文件中的一句代碼使用了一個(gè)float值, 如下所示:

void printFloat(){System.out.println(1234.5f);}

那么在這個(gè)類的常量池中就會(huì)有一個(gè)CONSTANT_Float_info與之相對(duì)應(yīng), 這個(gè)CONSTANT_Float_info的形式如下:


代碼反編譯結(jié)果如下:

Constant pool:............. .............#29 = Float 1234.5f............ ............{............ ............void printFloat();flags:Code:stack=2, locals=1, args_size=10: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #29 // float 1234.5f5: invokevirtual #30 // Method java/io/PrintStream.println:(F)V8: returnLineNumberTable:line 10: 0line 11: 8LocalVariableTable:Start Length Slot Name Signature0 9 0 this Lcom/jg/zhang/TestInt; }

(5)CONSTANT_Long_info

一個(gè)常量池中的CONSTANT_Long_info數(shù)據(jù)項(xiàng), 可以看做是CONSTANT_Long類型的一個(gè)實(shí)例。 它存儲(chǔ)的是源文件中出現(xiàn)的long型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個(gè)字節(jié)也是一個(gè)tag值, 它的tag值為5, 也就是說(shuō), 當(dāng)虛擬機(jī)讀到一個(gè)tag值為5的數(shù)據(jù)項(xiàng)時(shí), 就知道這個(gè)數(shù)據(jù)項(xiàng)是一個(gè)CONSTANT_Long_info, 并且知道它存儲(chǔ)的是long型數(shù)值。 緊挨著tag的下面8個(gè)字節(jié)叫做bytes, 就是long型的數(shù)值。 它的內(nèi)存布局如下:

舉例說(shuō)明, 如果源文件中的一句代碼使用了一個(gè)long型的數(shù)值, 如下所示:

void printLong(){System.out.println(123456L);}

那么在這個(gè)類的常量池中就會(huì)有一個(gè)CONSTANT_Long_info與之相對(duì)應(yīng), 這個(gè)CONSTANT_Long_info的形式如下:

代碼反編譯結(jié)果為:

Constant pool:.............. ..............#21 = Long 123456l.............. ..............{.............. ..............void printLong();flags:Code:stack=3, locals=1, args_size=10: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc2_w #21 // long 123456l6: invokevirtual #23 // Method java/io/PrintStream.println:(J)V9: returnLineNumberTable:line 7: 0line 8: 9LocalVariableTable:Start Length Slot Name Signature0 10 0 this Lcom/jg/zhang/TestInt; }

(6)CONSTANT_Double_info

一個(gè)常量池中的CONSTANT_Double_info數(shù)據(jù)項(xiàng), 可以看做是CONSTANT_Double類型的一個(gè)實(shí)例。 它存儲(chǔ)的是源文件中出現(xiàn)的double型數(shù)據(jù)的值。 同樣, 作為常量池中的一種數(shù)據(jù)類型, 它的第一個(gè)字節(jié)也是一個(gè)tag值, 它的tag值為6, 也就是說(shuō), 當(dāng)虛擬機(jī)讀到一個(gè)tag值為6的數(shù)據(jù)項(xiàng)時(shí), 就知道這個(gè)數(shù)據(jù)項(xiàng)是一個(gè)CONSTANT_Double_info, 并且知道它存儲(chǔ)的是double型數(shù)值。 緊挨著tag的下面8個(gè)字節(jié)叫做bytes, 就是double型的數(shù)值。 它的內(nèi)存布局如下:


舉例說(shuō)明, 如果源文件中的一句代碼使用了一個(gè)double型的數(shù)值, 如下所示:

void printDouble(){System.out.println(123456D);}

那么在這個(gè)類的常量池中就會(huì)有一個(gè)CONSTANT_Double_info與之相對(duì)應(yīng), 這個(gè)CONSTANT_Double_info的形式如下:

代碼反編譯結(jié)果為:

Constant pool:.............. ..............#21 = Double 123456.0d.............. ..............{.............. ..............void printDouble();flags:Code:stack=3, locals=1, args_size=10: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc2_w #21 // double 123456.0d6: invokevirtual #23 // Method java/io/PrintStream.println:(D)V9: returnLineNumberTable:line 7: 0line 8: 9LocalVariableTable:Start Length Slot Name Signature0 10 0 this Lcom/jg/zhang/TestInt; }

(7) CONSTANT_String_info

在常量池中, 一個(gè)CONSTANT_String_info數(shù)據(jù)項(xiàng), 是CONSTANT_String類型的一個(gè)實(shí)例。 它的作用是存儲(chǔ)文字字符串, 可以把他看做是一個(gè)存在于class文件中的字符串對(duì)象。 同樣, 它的第一個(gè)字節(jié)是tag值, 值為8 , 也就是說(shuō), 虛擬機(jī)訪問(wèn)一個(gè)數(shù)據(jù)項(xiàng)時(shí), 判斷tag值為8 , 就說(shuō)明訪問(wèn)的數(shù)據(jù)項(xiàng)是一個(gè)CONSTANT_String_info 。 緊挨著tag的后兩個(gè)字節(jié)是一個(gè)叫做string_index的常量池引用, 它指向一個(gè)CONSTANT_Utf8_info, 這個(gè)CONSTANT_Utf8_info存放的才是字符串的字面量。 它的內(nèi)存布局如下:

舉例說(shuō)明, 如果源文件中的一句代碼使用了一個(gè)字符串常量, 如下所示:

void printStrng(){System.out.println("abcdef");}

那么在這個(gè)類的常量池中就會(huì)有一個(gè)CONSTANT_String_info與之相對(duì)應(yīng), 反編譯結(jié)果如下:

Constant pool:.............. ..............#21 = String #22 // abcdef#22 = Utf8 abcdef.............. ..............{.............. ..............void printStrng();flags:Code:stack=2, locals=1, args_size=10: getstatic #15 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #21 // String abcdef5: invokevirtual #23 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 7: 0line 8: 8LocalVariableTable:Start Length Slot Name Signature0 9 0 this Lcom/jg/zhang/TestInt; }

其中printString方法中索引為3的字節(jié)碼指令ldc引用常量池中的第21項(xiàng), 第21項(xiàng)是一個(gè)CONSTANT_String_info, 這個(gè)位于第21項(xiàng)的CONSTANT_String_info又引用了常量池的第22項(xiàng), 第22項(xiàng)是一個(gè)CONSTANT_Utf8_info, 這個(gè)CONSTANT_Utf8_info中存儲(chǔ)的字符串是 abcdef 。 引用關(guān)系的內(nèi)存布局如下:


總結(jié)

本文就到此為止。 最后總結(jié)一下, 本文主要講解了常量池中的五中數(shù)據(jù)項(xiàng), 分別為CONSTANT_Integer_info, CONSTANT_Float_info, CONSTANT_Long_info, CONSTANT_Double_info 和CONSTANT_String_info 。 這幾種常量池?cái)?shù)據(jù)項(xiàng)都是直接存儲(chǔ)的常量值,而不是符號(hào)引用。 這里又一次出現(xiàn)了符號(hào)引用的概念, 這個(gè)概念將會(huì)在下一篇博客中詳細(xì)講解, 因?yàn)橄乱黄┛鸵榻B的剩下的四種常量池?cái)?shù)據(jù)項(xiàng), 都是符號(hào)引用, 這四種表示符號(hào)引用的數(shù)據(jù)項(xiàng)又會(huì)直接或間接引用上篇文章中介紹的CONSTANT_NameAndType_info和CONSTANT_Utf8_info, 所以說(shuō)CONSTANT_NameAndType_info是符號(hào)引用的一部分。

從本文中我們還可以知道。 雖然說(shuō)CONSTANT_String_info是直接存儲(chǔ)值的數(shù)據(jù)項(xiàng), 但是CONSTANT_String_info有點(diǎn)特別, 因?yàn)樗皇侵苯哟鎯?chǔ)字符串, 而是引用了一個(gè)CONSTANT_Utf8_info, 這個(gè)被引用的CONSTANT_Utf8_info中存儲(chǔ)了字符串。

最后, 列出下一篇博文要介紹的剩下的四種常量池?cái)?shù)據(jù)項(xiàng):
CONSTANT_Class_info
CONSTANT_Fieldref_info
CONSTANT_Methodref_info
CONSTANT_InterfaceMethodref_info

總結(jié)

以上是生活随笔為你收集整理的深入理解 JVM Class文件格式(四)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。