亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Java常量池知識點總結

2024-07-13 10:15:01
字體:
來源:轉載
供稿:網友

java常量池是一個經久不衰的話題,也是面試官的最愛,題目花樣百出,這次好好總結一下。

理論

先拙劣的表達一下jvm虛擬內存分布:

Java,常量池

程序計數器是jvm執行程序的流水線,存放一些跳轉指令,這個太高深,不懂。

本地方法棧是jvm調用操作系統方法所使用的棧。

虛擬機棧是jvm執行java代碼所使用的棧。

方法區存放了一些常量、靜態變量、類信息等,可以理解成class文件在內存中的存放位置。

虛擬機堆是jvm執行java代碼所使用的堆。 

Java中的常量池,實際上分為兩種形態:靜態常量池運行時常量池。

所謂靜態常量池,即*.class文件中的常量池,class文件中的常量池不僅僅包含字符串(數字)字面量,還包含類、方法的信息,占用class文件絕大部分空間。

運行時常量池,則是jvm虛擬機在完成類裝載操作后,將class文件中的常量池載入到內存中,并保存在方法區中,我們常說的常量池,就是指方法區中的運行時常量池。

接下來我們引用一些網絡上流行的常量池例子,然后借以講解。

String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo"; String s4 = "Hel" + new String("lo"); String s5 = new String("Hello"); String s6 = s5.intern(); String s7 = "H"; String s8 = "ello"; String s9 = s7 + s8;System.out.println(s1 == s2); // trueSystem.out.println(s1 == s3); // trueSystem.out.println(s1 == s4); // falseSystem.out.println(s1 == s9); // falseSystem.out.println(s4 == s5); // falseSystem.out.println(s1 == s6); // true

首先說明一點,在java 中,直接使用==操作符,比較的是兩個字符串的引用地址,并不是比較內容,比較內容請用String.equals()。

s1 == s2這個非常好理解,s1、s2在賦值時,均使用的字符串字面量,說白話點,就是直接把字符串寫死,在編譯期間,這種字面量會直接放入class文件的常量池中,從而實現復用,載入運行時常量池后,s1、s2指向的是同一個內存地址,所以相等。

s1 == s3這個地方有個坑,s3雖然是動態拼接出來的字符串,但是所有參與拼接的部分都是已知的字面量,在編譯期間,這種拼接會被優化,編譯器直接幫你拼好,因此String s3 = "Hel" + "lo";在class文件中被優化成String s3 = "Hello";,所以s1 == s3成立。

s1 == s4當然不相等,s4雖然也是拼接出來的,但new String("lo")這部分不是已知字面量,是一個不可預料的部分,編譯器不會優化,必須等到運行時才可以確定結果,結合字符串不變定理,鬼知道s4被分配到哪去了,所以地址肯定不同。配上一張簡圖理清思路:

Java,常量池     

s1 == s9也不相等,道理差不多,雖然s7、s8在賦值的時候使用的字符串字面量,但是拼接成s9的時候,s7、s8作為兩個變量,都是不可預料的,編譯器畢竟是編譯器,不可能當解釋器用,所以不做優化,等到運行時,s7、s8拼接成的新字符串,在堆中地址不確定,不可能與方法區常量池中的s1地址相同。

Java,常量池

s4 == s5已經不用解釋了,絕對不相等,二者都在堆中,但地址不同。

s1 == s6這兩個相等完全歸功于intern方法,s5在堆中,內容為Hello ,intern方法會嘗試將Hello字符串添加到常量池中,并返回其在常量池中的地址,因為常量池中已經有了Hello字符串,所以intern方法直接返回地址;而s1在編譯期就已經指向常量池了,因此s1和s6指向同一地址,相等。

至此,我們可以得出三個非常重要的結論:

必須要關注編譯期的行為,才能更好的理解常量池。

運行時常量池中的常量,基本來源于各個class文件中的常量池。

程序運行時,除非手動向常量池中添加常量(比如調用intern方法),否則jvm不會自動添加常量到常量池。

以上所講僅涉及字符串常量池,實際上還有整型常量池、浮點型常量池等等,但都大同小異,只不過數值類型的常量池不可以手動添加常量,程序啟動時常量池中的常量就已經確定了,比如整型常量池中的常量范圍:-128~127,只有這個范圍的數字可以用到常量池。

實踐

說了這么多理論,接下來讓我們觸摸一下真正的常量池。

前文提到過,class文件中存在一個靜態常量池,這個常量池是由編譯器生成的,用來存儲java源文件中的字面量(本文僅僅關注字面量),假設我們有如下java代碼:

String s = "hi";

為了方便起見,就這么簡單,沒錯!將代碼編譯成class文件后,用winhex打開二進制格式的class文件。如圖:

Java,常量池

簡單講解一下class文件的結構,開頭的4個字節是class文件魔數,用來標識這是一個class文件,說白話點就是文件頭,既:CA FE BA BE。

緊接著4個字節是java的版本號,這里的版本號是34,因為筆者是用jdk8編譯的,版本號的高低和jdk版本的高低相對應,高版本可以兼容低版本,但低版本無法執行高版本。所以,如果哪天讀者想知道別人的class文件是用什么jdk版本編譯的,就可以看這4個字節。

接下來就是常量池入口,入口處用2個字節標識常量池常量數量,本例中數值為00 1A,翻譯成十進制是26,也就是有25個常量,其中第0個常量是特殊值,所以只有25個常量。

常量池中存放了各種類型的常量,他們都有自己的類型,并且都有自己的存儲規范,本文只關注字符串常量,字符串常量以01開頭(1個字節),接著用2個字節記錄字符串長度,然后就是字符串實際內容。本例中為:01 00 02 68 69。

接下來再說說運行時常量池,由于運行時常量池在方法區中,我們可以通過jvm參數:-XX:PermSize、-XX:MaxPermSize來設置方法區大小,從而間接限制常量池大小。

假設jvm啟動參數為:-XX:PermSize=2M -XX:MaxPermSize=2M,然后運行如下代碼:

//保持引用,防止自動垃圾回收List<String> list = new ArrayList<String>();int i = 0;while(true){//通過intern方法向常量池中手動添加常量  list.add(String.valueOf(i++).intern());}

 

程序立刻會拋出:Exception in thread "main" java.lang.outOfMemoryError: PermGen space異常。PermGen space正是方法區,足以說明常量池在方法區中。

在jdk8中,移除了方法區,轉而用Metaspace區域替代,所以我們需要使用新的jvm參數:-XX:MaxMetaspaceSize=2M,依然運行如上代碼,拋出:java.lang.OutOfMemoryError: Metaspace異常。同理說明運行時常量池是劃分在Metaspace區域中。具體關于Metaspace區域的知識,請讀者自行搜索。

本文所有代碼均在jdk7、jdk8下測試通過,其他版本jdk可能會略有差異,請讀者自行探索。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩爱爱视频| 性欧美在线看片a免费观看| 日韩精品一区二区三区第95| 久久免费少妇高潮久久精品99| 91色在线观看| 亚洲精品久久在线| www.欧美精品一二三区| 色综合天天综合网国产成人网| 美女少妇精品视频| 全亚洲最色的网站在线观看| 精品久久中文字幕| 亚洲天堂av综合网| 欧美日韩不卡合集视频| 欧美激情在线一区| 日韩高清电影好看的电视剧电影| 91在线观看免费观看| 日韩在线中文视频| 国产香蕉97碰碰久久人人| 亚洲精品国产综合区久久久久久久| 国产精品一区二区三区成人| 欧美理论电影网| 欧美限制级电影在线观看| 亚洲最新在线视频| 欧美日韩中文字幕日韩欧美| 亚洲电影免费观看| 成人免费激情视频| 欧美日韩国产中文精品字幕自在自线| 国产亚洲精品一区二555| 中文字幕亚洲自拍| 少妇高潮 亚洲精品| 精品国模在线视频| 成人黄色免费网站在线观看| 久久成人精品电影| 国产精品亚洲综合天堂夜夜| 亚洲精品色婷婷福利天堂| 欧美色播在线播放| 免费不卡欧美自拍视频| 欧美在线视频a| 中文字幕av一区二区三区谷原希美| 日韩成人av网址| 国产精品久久久久久久电影| 日韩在线播放一区| 96pao国产成视频永久免费| 日本成熟性欧美| 久99九色视频在线观看| 国产精品永久在线| 亚洲女性裸体视频| 中文字幕亚洲一区二区三区| 成人欧美一区二区三区黑人孕妇| 亚洲国产高清高潮精品美女| 欧美日韩裸体免费视频| 日韩精品电影网| 久久精品99国产精品酒店日本| 久久伊人精品一区二区三区| 国内精品一区二区三区四区| 欧美午夜精品久久久久久久| 久久国产精品久久国产精品| 国产成人精品久久亚洲高清不卡| 亚洲天堂av综合网| 中文字幕欧美日韩va免费视频| 成人免费观看49www在线观看| 国产精品成人品| www欧美xxxx| 国产精品一区二区三区免费视频| 国产精品日韩久久久久| 91免费国产网站| 欧美日韩成人在线视频| 久久久成人的性感天堂| 日产日韩在线亚洲欧美| 91香蕉亚洲精品| 日韩av在线免费观看一区| 欧美一区二区三区艳史| 久久综合免费视频| 国产精品日日做人人爱| 欧美激情第一页xxx| 成人免费网站在线观看| 色偷偷噜噜噜亚洲男人的天堂| 午夜精品久久久久久久99黑人| 欧美国产亚洲视频| 国产精品三级久久久久久电影| 日本一区二三区好的精华液| 欧美大胆在线视频| 国产日韩亚洲欧美| 国产99久久精品一区二区| 欧亚精品中文字幕| 国产高清视频一区三区| 久久天堂av综合合色| 伊人伊成久久人综合网小说| 亚洲伊人第一页| 久久久国产视频91| 精品久久久久久亚洲精品| 国产婷婷成人久久av免费高清| 久久精品青青大伊人av| 成人午夜黄色影院| 夜夜嗨av色综合久久久综合网| 98精品国产自产在线观看| 美女性感视频久久久| 日韩中文字幕免费| 亚洲国产另类 国产精品国产免费| 亚洲香蕉伊综合在人在线视看| 欧美性猛交xxxx免费看漫画| 亚洲美女喷白浆| 久久国产精彩视频| 欧美日韩国产综合新一区| 国产成+人+综合+亚洲欧美丁香花| 国产综合在线看| 亚洲三级黄色在线观看| 亚洲国产精品人久久电影| 亚洲精品aⅴ中文字幕乱码| 久久久久久午夜| 欧美大秀在线观看| 国产精品∨欧美精品v日韩精品| 国产精品免费福利| 91国产精品视频在线| 韩剧1988免费观看全集| 日韩中文在线中文网三级| 亚洲精品v天堂中文字幕| 国产一区深夜福利| 日韩欧美中文在线| 欧洲一区二区视频| 欧美最猛黑人xxxx黑人猛叫黄| 中文字幕亚洲欧美在线| 91久久嫩草影院一区二区| 日韩精品视频中文在线观看| 亚洲美女www午夜| 高跟丝袜一区二区三区| 精品无人区太爽高潮在线播放| 久久免费精品日本久久中文字幕| 欧美精品在线观看| 亚洲人成网站在线播| 在线丨暗呦小u女国产精品| 欧美大片免费观看在线观看网站推荐| 日韩亚洲国产中文字幕| 九九久久综合网站| 国语自产精品视频在线看抢先版图片| 亚洲国产美女精品久久久久∴| 亚洲成人网在线| 久久视频在线免费观看| 亚洲第一福利网站| 久久久久久午夜| 精品中文字幕在线2019| 久久久久久久网站| 亚洲va欧美va国产综合久久| 国产精品自产拍高潮在线观看| 欧美精品久久久久久久久久| 黄色成人av网| 国产精品午夜国产小视频| 亚洲毛片在线观看.| 日韩欧美在线免费| 一区二区三区美女xx视频| 成人高h视频在线| 国产日本欧美一区二区三区在线| 青青精品视频播放| 亚洲天堂一区二区三区| 岛国精品视频在线播放| 国产亚洲精品久久久久动| 国内精品久久久久| 欧美大片在线免费观看| 国产日产亚洲精品| 精品国产精品三级精品av网址| 国产精品丝袜视频| 亚洲视频免费一区| 亚洲国产一区二区三区在线观看| 亚洲欧洲一区二区三区久久|