最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM字符串常量池StringTable的具體使用

 更新時(shí)間:2024年04月12日 08:58:46   作者:zoeil  
字符串常量池是JVM中的一個(gè)重要結(jié)構(gòu),用于存儲(chǔ)JVM運(yùn)行時(shí)產(chǎn)生的字符串,本文主要介紹了JVM字符串常量池StringTable的具體使用,感興趣的可以了解一下

一、StringTable為什么要調(diào)整

jdk7之前,hotspot對于方法區(qū)的實(shí)現(xiàn)是永久代,常量池包括字符串常量池放于永久代中;

jdk7時(shí),hotspot將字符串常量池(還有靜態(tài)變量)放在了堆中。有一點(diǎn)“去永久代”的苗頭

jdk8之后,hotspot取出永久代,取而代之的是使用本地內(nèi)存的元空間。字符串常量池還是在堆中。

為什么要將字符串常量池StringTable放在堆中?

jdk7中將StringTable放到了堆空間中,因?yàn)橛谰么幕厥招屎艿?。在fullGC的時(shí)候才觸發(fā),而fullGC是老年代空間不足,永久代不足時(shí)才觸發(fā),觸發(fā)次數(shù)較少,甚至在開發(fā)中我們要避免出現(xiàn)fullGC。這就導(dǎo)致了StringTable回收效率不高,而我們開發(fā)中會(huì)創(chuàng)建大量的字符串,回收效率低,導(dǎo)致永久代內(nèi)存不足。放到堆里,能及時(shí)回收內(nèi)存。

二、String的基本特性

jdk8及以前,內(nèi)部定義了final char[] value用于存儲(chǔ)字符串?dāng)?shù)據(jù)

JDK9時(shí)改為byte[] + 字符類型標(biāo)記,為什么做出這個(gè)改變呢?

char數(shù)組一個(gè)char占16bits(兩個(gè)字節(jié)),String是堆空間的主要部分,大部分是latin-1字符,一個(gè)字節(jié)就夠了,這樣會(huì)有一半空間浪費(fèi)。所以采用byte數(shù)組+字符串類型,如果是中文等UTF-16 的用兩個(gè)字節(jié)存儲(chǔ)。

StringBuffer,StringBuilder同樣做了修改

String為什么不可變?

因?yàn)榈讓訑?shù)組被final修飾。而且其類自身也被final修飾,這就導(dǎo)致了不能通過繼承去修改其內(nèi)部結(jié)構(gòu)。保證了其不可變性。

  • 當(dāng)字符串重新賦值,需要重寫指定內(nèi)存區(qū)域賦值,不能使用原有的value進(jìn)行賦值
  • 當(dāng)對現(xiàn)有的字符串進(jìn)行連接操作時(shí),也需要重新指定內(nèi)存區(qū)域賦值,不能對使用原有的value進(jìn)行賦值
  • 當(dāng)調(diào)用String的replace方法修改指定字符或字符串時(shí),也需要重新指定內(nèi)存區(qū)域賦值,不能使用原有的value進(jìn)行賦值。

字符串常量池中不會(huì)存儲(chǔ)相同的字符串的

String的String pool是一個(gè)固定大小的HashTable,默認(rèn)大小長度是1009,如果放進(jìn)String Pool的String非常多,就會(huì)造成Hash沖突嚴(yán)重,從而導(dǎo)致鏈表會(huì)很長,而鏈表長了,直接影響就是調(diào)用String.intern時(shí)性能會(huì)大幅下降

  • -XX:StringTableSize可設(shè)置StringTable的大小
  • JDK6固定1009,jdk7中StringTable默認(rèn)的長度是60013,JDK8時(shí)默認(rèn)是60013,1009是可設(shè)置的最小值

三、String的內(nèi)存分配

Java語言中有8種基本數(shù)據(jù)類型和一種比較特殊的類型String,這些類型為了使他們再運(yùn)行過程中速度更快,更節(jié)省內(nèi)存,都提供了一種常量池的概念

String的常量池比較特殊,主要使用方法有兩種

  • 直接使用雙引號,聲明出來的String對象會(huì)直接存儲(chǔ)在常量池中
  • 如果不是雙引號聲明的String對象,可以使用String提供的intern()方法

jdk6及之前,字符串常量池存在永久代

jdk7中,字符串常量池調(diào)整到Java堆中,調(diào)優(yōu)時(shí)僅需調(diào)整堆大小就可以

四、字符串拼接操作

常量與常量的拼接結(jié)果在常量池,原理是編譯期優(yōu)化

只要其中有一個(gè)變量,拼接結(jié)果就在堆中(常量池以外的堆),變量的拼接原理是StringBuilder 

String res  = s1 + s2; 
// 實(shí)際上是StringBuilder s = new StringBuilder().append(s1).append(s2); 
// 然后調(diào)用s.toString();

如果拼接的結(jié)果調(diào)用intern方法,則主動(dòng)將常量池中還沒有的字符串對象放入池中,并返回此對象地址

字符串拼接操作不一定使用的是StringBuilder如果拼接符號左右兩邊都是字符串常量或常量引用,則仍然使用編譯期優(yōu)化,即非StringBuilder的方式

針對final修飾類,方法,基本數(shù)據(jù)類型,引用數(shù)據(jù)類型變量的結(jié)構(gòu)時(shí),能使用final盡量使用上

五、intern()方法

jdk1.6中,將這個(gè)字符串對象放入串池

  • 如果串池中有,則并不會(huì)放入,返回已有串池中的對象的地址,
  • 如果沒有,會(huì)把對象復(fù)制一份,放入串池,并返回串池中的對象地址

jdk1.7起,將這個(gè)字符串對象嘗試放入串池

  • 如果串池中有,則并不會(huì)放入,返回已有的串池中的對象的地址
  • 如果沒有,則會(huì)把對象的引用地址復(fù)制一份,放入串池,并返回串池中的引用地址

例子:

前置知識

newString("ab")會(huì)創(chuàng)建幾個(gè)對象?

2個(gè)對象,查看字節(jié)碼驗(yàn)證。一個(gè)是常量池ab,一個(gè)是new出來在堆空間。(前提是常量池沒有ab)

new String("a")+new String("b")?

  • 對象1,有拼接操作就newStringBuilder
  • 對象2,new一個(gè)String
  • 對象3,常量池a
  • 對象4,new String
  • 對象5,常量池b
  • 對象6,StringBuilder,toString方法會(huì)new String返回
    • 注意:toString方法這里new String并不會(huì)向字符串常量池中放入"ab",不像我們平時(shí)上面一樣會(huì)放入一個(gè)“ab”在常量池中。

結(jié)果

jdk6        false false

jdk7/8        false true

分析:

jdk6的intern會(huì)復(fù)制一份"1"放入字符串常量池。但是new的時(shí)候其實(shí)已經(jīng)放入常量池了,所以這里intern沒啥用,此時(shí)s2拿到的就是常量池的那一份。而s是指向堆中new出來的String對象,所以為false

s3這里intern的時(shí)候常量池沒有“11”,所以會(huì)復(fù)制一份放入常量池,此時(shí)s4拿到的就是常量池的那一份。而s3指向堆中new出來的String對象,所以為false

jdk7/8的intern是復(fù)制引用地址放入字符串常量池,但是new的時(shí)候其實(shí)已經(jīng)放入常量池了,所以這里intern沒啥用,此時(shí)s2拿到的就是常量池的那一份。所以為false

s3這里intern的時(shí)候常量池沒有“11”,所以會(huì)復(fù)制引用放入常量池,此時(shí)s4拿到的就是常量池的那一份引用。而s3也指向堆中new出來的String對象,所以為true

六、Stringtable的垃圾回收

-XX:+PrintStringTableStatistics

七、G1中String去重操作

背景:對許多Java應(yīng)用,做的測試結(jié)果如下

  • 堆存貨數(shù)據(jù)集合里面String對象占了25%
  • 堆存活數(shù)據(jù)集合里面重復(fù)的String對象有13.5%
  • String對象的平均長度是45

許多大規(guī)模的Java應(yīng)用的瓶頸在于內(nèi)存。Java堆中存活的數(shù)據(jù)集合差不多25%是String對象,這里差不多一半的String對象是重復(fù)的, 重復(fù)是指equals方法=true,堆上重復(fù)的String對象必然是一種內(nèi)存的浪費(fèi)。G1垃圾收集器中實(shí)現(xiàn)自動(dòng)持續(xù)對重復(fù)的String對象進(jìn)行去重,這樣避免浪費(fèi)。

到此這篇關(guān)于JVM字符串常量池StringTable的具體使用的文章就介紹到這了,更多相關(guān)JVM字符串常量池StringTable內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • 深入了解Java核心類庫--Objects類

    深入了解Java核心類庫--Objects類

    這篇文章主要介紹了Java中的Object類詳細(xì)介紹,本文講解了Object類的作用、Object類的主要方法、Object類中不能被重寫的方法、Object類的equals方法重寫實(shí)例等內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Spring Boot 實(shí)例化bean如何選擇代理方式

    Spring Boot 實(shí)例化bean如何選擇代理方式

    這篇文章主要為大家介紹了Spring Boot實(shí)例化bean如何選擇代理方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Java實(shí)現(xiàn)大文件的切割與合并操作示例

    Java實(shí)現(xiàn)大文件的切割與合并操作示例

    這篇文章主要介紹了Java實(shí)現(xiàn)大文件的切割與合并操作,結(jié)合實(shí)例形式分析了java基于io及util操作大文件按指定個(gè)數(shù)分割與合并相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • CorsFilter 過濾器解決跨域的處理

    CorsFilter 過濾器解決跨域的處理

    這篇文章主要介紹了CorsFilter 過濾器解決跨域的處理操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java實(shí)現(xiàn)郵件發(fā)送的過程及代碼詳解

    Java實(shí)現(xiàn)郵件發(fā)送的過程及代碼詳解

    這篇文章主要介紹了Java實(shí)現(xiàn)郵件發(fā)送的過程及代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Spring Boot應(yīng)用與Prometheus和Grafana整合方案

    Spring Boot應(yīng)用與Prometheus和Grafana整合方案

    通過將Spring Boot應(yīng)用與Prometheus和Grafana進(jìn)行整合,我們可以實(shí)現(xiàn)對Spring Boot應(yīng)用的全面監(jiān)控和可視化展示,本文將詳細(xì)介紹如何將Spring Boot應(yīng)用與Prometheus和Grafana進(jìn)行整合,實(shí)現(xiàn)對Spring Boot應(yīng)用的全面監(jiān)控,感興趣的朋友一起看看吧
    2025-11-11
  • mybatis整合springboot報(bào)BindingException:Invalid?bound?statement?(not?found)異常解決

    mybatis整合springboot報(bào)BindingException:Invalid?bound?stateme

    這篇文章主要給大家介紹了關(guān)于mybatis整合springboot報(bào)BindingException:Invalid?bound?statement?(not?found)異常的解決辦法,這個(gè)錯(cuò)誤通常是由于Mapper文件中的statement?id與Java代碼中的方法名不一致導(dǎo)致的,需要的朋友可以參考下
    2024-01-01
  • Java實(shí)現(xiàn)從Word文檔中提取文本和圖像

    Java實(shí)現(xiàn)從Word文檔中提取文本和圖像

    在 Java 開發(fā)項(xiàng)目中,處理 Microsoft Word 文檔是常見場景,例如,內(nèi)容管理系統(tǒng)需要批量解析文檔文本用于搜索索引,數(shù)據(jù)遷移工具需分離圖像以便獨(dú)立存儲(chǔ),本文介紹如何借助 Spire.Doc for Java 庫實(shí)現(xiàn)這一功能,需要的朋友可以參考下
    2026-03-03
  • 基于@Valid和@Validated驗(yàn)證List集合的踩坑記錄

    基于@Valid和@Validated驗(yàn)證List集合的踩坑記錄

    這篇文章主要介紹了基于@Valid和@Validated驗(yàn)證List集合的踩坑記錄,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 一文帶你快速了解java中的static關(guān)鍵詞

    一文帶你快速了解java中的static關(guān)鍵詞

    這篇文章主要給大家介紹了關(guān)于java中static關(guān)鍵詞的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論

沂源县| 商水县| 驻马店市| 凯里市| 时尚| 扶余县| 永康市| 长海县| 延寿县| 龙海市| 马公市| 乐至县| 和顺县| 宁晋县| 濮阳市| 沙洋县| 扶余县| 乳源| 永兴县| 周口市| 富源县| 区。| 运城市| 阳谷县| 县级市| 南投市| 泗水县| 石阡县| 剑川县| 平远县| 洪泽县| 长垣县| 宝丰县| 家居| 普兰店市| 紫金县| 嘉祥县| 鸡西市| 都昌县| 介休市| 武安市|