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

詳解JVM 中的StringTable

 更新時間:2021年03月05日 08:35:20   作者:萌新J  
這篇文章主要介紹了JVM 中的StringTable,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

是什么

字符串常量池是 JVM中的一個重要結(jié)構(gòu),用于存儲JVM運行時產(chǎn)生的字符串。在JDK7之前在方法區(qū)中,存儲的是字符串常量。而字符串常量池在 JDK7開始移入堆中,隨之而來的是除了存儲字符串常量外,還可以存儲字符串引用(因為在堆中,引用堆中的字符串常量很方便,所以可以存儲引用)。這使得很多字符串的操作在 JDK7中和在之前的版本中執(zhí)行是不同的結(jié)果。這也是為什么字符串相關(guān)的問題是如此具有迷惑性的原因之一。

底層

String:在 JDK9之前,String底層是使用 char數(shù)組來存儲字符串?dāng)?shù)據(jù)的,而在 JDK9開始,使用 byte數(shù)組+編碼來代替 char數(shù)組,這是為了節(jié)省空間,因為不同編碼的數(shù)據(jù)占空間不一樣,很多單位數(shù)據(jù)只需要一個 byte(8字節(jié)) 就可以存儲,而使用 char(16字節(jié))就會浪費多余的空間。

字符串常量池:底層使用 HashTable來存儲字符串,在 JDK6 HashTable的數(shù)組長度是1006,JDK7開始變成了 60013,這是為了避免存儲字符串過多導(dǎo)致鏈表長度過長從而查詢效率降低??梢允褂脜?shù) -XX:StringTableSize=來設(shè)置 StringTable數(shù)組的長度。

常見問題字符串相加

1、對于字符串常量相加,編譯器會優(yōu)化成直接相加。

如 String ss = "a" + "b",在編譯器的優(yōu)化下,實際上只會創(chuàng)建一個 "ab" 字符串。

而 final String s1 = "a"; String s2 = s1+"b",除了創(chuàng)建字符串 "a"外,只會創(chuàng)建 "ab"。

操作相關(guān)字符串如下:

可以看到只對字符串 "a"、"ab"進行了入池操作(ldc)

2、對于包含字符串變量的相加,不會在字符串常量池中創(chuàng)建對應(yīng)的字符串。
如 String s1 = "a"; String s2 = s1 + "b",執(zhí)行完后字符串常量池中只會包含 "a"、"b" 字符串。

對于 s1 + "b",下面是其字節(jié)碼操作

可以看到,相加操作實際上是調(diào)用 StringBuilder的append方法進行字符串拼接,然后調(diào)用它的 toString方法獲取返回值保存輸出,期間并沒有入池操作(ldc)。

由此得出的優(yōu)化建議:因為每次執(zhí)行一次包含非常量的字符串相加時,都進行了一次 StringBuilder對象的創(chuàng)建,所以如果需要多次連接,可以直接創(chuàng)建 StringBuilder對象,使用一個 StringBuilder對象進行字符串拼接,避免創(chuàng)建多個對象降低效率。

對象創(chuàng)建數(shù)量

對象,包括 new的對象以及字符串對象。

1、對于String ss = new String ("ab"),這個過程首先會在會在字符串常量池中創(chuàng)建一個 "ab"字符串常量,然后再在堆上創(chuàng)建一個 new String()的對象,在這個對象中會保存常量池中 "ab"的地址信息,最后在棧上創(chuàng)建一個局部變量 ss ,保存堆中創(chuàng)建的對象地址。所以全程創(chuàng)建了堆中的一個對象和字符串常量池中的一個對象。

2、new String("a") + new String("b")。嚴(yán)格來看,創(chuàng)建了六個對象。

首先new String("a")和 new String("b") ,分為創(chuàng)建了兩個對象。兩者相加時,會創(chuàng)建一個 StringBuilder對象,而在 StringBuilder.toString()方法中,也會創(chuàng)建一個 String對象

3、String s1 = "a", String s2 = "b", String s3 = "a" + "b" + s1 + "c" + s2;對應(yīng)的字節(jié)碼如下:

字符串常量池中會有四個字符串對象,分別是 "a"、"b"、"ab"、"c"。在開始因為 s1、s2的賦值,會將 "a"、"b"分別加入字符串常量池,然后執(zhí)行第三步,運行順序是從左到右,首先執(zhí)行 "a" + "b" ,因為兩個都是常量,所以會因為編譯器的優(yōu)化直接返回 "ab",并且因為計算的兩個參數(shù)都是常量,所以直接加入字符串常量池,隨后因為與變量 s1相加,所以調(diào)用 StringBuilder的append方法,得到的結(jié)果保存到局部變量表中,所以引入常量 "c",因為是常量,所以還是會引入字符串常量池,然后與前面拼接得到的結(jié)果再次拼接,最后再與變量 s2相加,因為不是常量所以還是不會將結(jié)果加入字符串常量池。

除此之外,還需要注意,上面三種情況是在初始情況下,也就是字符串常量池中沒有要加入的字符串時的場景,如果字符串常量池中預(yù)先就包含要加入的字符串,那么就會直接將常量池中的對應(yīng)的字符串地址返回給調(diào)用方。比如 String s1 = "a",在常量池中沒有 "a"時,創(chuàng)建的對象是 1個,而如果常量池中已經(jīng)存在,那么就會將其地址直接返回賦給 s1。那么創(chuàng)建的對象就是 0個了。

intern()與字符串相等判斷

intern()方法是 String類的一個native方法,作用是嘗試將調(diào)用這個方法的字符串對象加入字符串常量池中,然后返回常量池中存儲的值。在開頭說過,在 JDK7開始字符串常量池可以存儲字符串引用,導(dǎo)致字符串操作的過程可能會之前不一樣,從而得到不同的結(jié)果。

intern()方法的執(zhí)行:

1.6及之前:嘗試將當(dāng)前字符串常量加入常量池,如果常量池存在就返回地址值;如果不存在就先加入常量池,然后再返回加入位置的地址值。

1.7開始:嘗試將當(dāng)前字符串常量加入常量池,如果存在就將返回地址值;如果不存在就存入當(dāng)前 String 字符串的地址值。

下面以一個例子來解釋一下,在JDK7和JDK7之前下面代碼執(zhí)行分別是什么結(jié)果。

@Test
 public void test1(){
  String s = new String("1");
  s.intern();
  String s2 = "1";
  System.out.println(s == s2);


  String s3 = new String("1") + new String("1");
  s3.intern();
  String s4 = "11";
  System.out.println(s3 == s4);
 }

先說結(jié)論:

JDK7之前: false、false。

JDK7及之后:false、true。

原因:

1、首先先看上面 3------6行的,首先,第三行會在字符串常量池中添加 "1" ,然后在堆中創(chuàng)建一個對象,保存 "1"在常量池中的地址,再在局部變量表中添加一個 s保存堆中對象的地址。隨后執(zhí)行第四行,此時 s指向的字符串已經(jīng)在常量池中了,所以這一步無效,第五行因為常量池已經(jīng)存在 "1" ,所以 JDK7或之前執(zhí)行的邏輯是一樣的,直接將 "1"在常量池中的地址返回給 s2。然后判斷,s指向的是堆中的對象,而 s2指向的是常量池中的字符串常量,所以無論是 JDK7還是之前的都是 false。

2、然后再看下面 9-----12行。因為前面已經(jīng)在常量池中添加 "1",所以第9行會直接返回地址,然后執(zhí)行添加操作,創(chuàng)建字符串 "11",此時并沒有添加到常量池,然后執(zhí)行第10行,因為常量池不存在 "11",所以 JDK7之前直接加入常量池,JDK7及以后則直接將 "11"的地址存入常量池,而 s3則不變,還是保存的是常量池外的那個 "11"的地址值。然后執(zhí)行 11行,因為常量池已存在 "11",所以 s4就是返回 "11"的地址值,不同的是在 JDK7之前因為常量池保存的是 "11"常量,所以返回的是常量池中的地址值;而 JDK7 及以后常量池保存的是常量池外的 "11"的地址值,所以返回的是池外的地址值。所以最后判斷在 JDK7之前是 false,而在 JDK7開始是 true。

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

相關(guān)文章

  • Spring cloud alibaba之Gateway網(wǎng)關(guān)功能特征詳解

    Spring cloud alibaba之Gateway網(wǎng)關(guān)功能特征詳解

    spring cloud gateway是spring cloud推出的第二代網(wǎng)關(guān),是由WebFlux+Netty+Reactor實現(xiàn)的響應(yīng)式的API網(wǎng)關(guān),它不能在傳統(tǒng)的servlet容器中工作,也不能構(gòu)建成war包,接下來通過本文給大家分享Spring cloud alibaba--Gateway網(wǎng)關(guān),需要的朋友可以參考下
    2021-08-08
  • Java中Connection timed out和Connection refused的區(qū)別講解

    Java中Connection timed out和Connection refused的區(qū)別講解

    今天小編就為大家分享一篇關(guān)于Java中Connection timed out和Connection refused的區(qū)別講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Java制作智能拼圖游戲原理及代碼

    Java制作智能拼圖游戲原理及代碼

    本文給大家分享的是使用Java實現(xiàn)智能拼圖游戲的原理,以及實現(xiàn)的源碼,推薦給大家,有需要的小伙伴可以參考下。
    2015-03-03
  • PowerJob的IdGenerateService工作流程源碼解讀

    PowerJob的IdGenerateService工作流程源碼解讀

    這篇文章主要為大家介紹了PowerJob的IdGenerateService工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • Java AQS中閉鎖CountDownLatch的使用

    Java AQS中閉鎖CountDownLatch的使用

    CountDownLatch 是一個同步工具類,用來協(xié)調(diào)多個線程之間的同步,它能夠使一個線程在等待另外一些線程完成各自工作之后,再繼續(xù)執(zhí)行。被將利用CountDownLatch實現(xiàn)網(wǎng)絡(luò)同步請求,異步同時獲取商品信息組裝,感興趣的可以了解一下
    2023-02-02
  • 使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫

    使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫

    這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • maven多模塊依賴版本不一致問題解決

    maven多模塊依賴版本不一致問題解決

    本文主要介紹了maven多模塊依賴版本不一致問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Java利用endorsed如何覆蓋jdk提供的類詳解

    Java利用endorsed如何覆蓋jdk提供的類詳解

    這篇文章主要給大家介紹了關(guān)于Java利用endorsed如何覆蓋jdk提供的類的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建)

    springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建)

    這篇文章主要介紹了springboot-2.3.x最新版源碼閱讀環(huán)境搭建(基于gradle構(gòu)建),需要的朋友可以參考下
    2020-08-08
  • Java設(shè)計模式之策略模式詳細解析

    Java設(shè)計模式之策略模式詳細解析

    這篇文章主要介紹了Java設(shè)計模式之策略模式詳細解析,策略模式中,定義算法族,分別封裝起來,讓他們之間可以相互轉(zhuǎn)化,此模式讓算法的變化獨立于使用算法的客戶,需要的朋友可以參考下
    2023-11-11

最新評論

邯郸市| 宣化县| 沙河市| 长沙县| 湘乡市| 独山县| 定边县| 巩留县| 沈阳市| 嘉荫县| 西乌珠穆沁旗| 潢川县| 北安市| 晋中市| 昌吉市| 乌拉特中旗| 将乐县| 金山区| 周至县| 吴川市| 延安市| 禹城市| 昌邑市| 古浪县| 曲靖市| 长宁区| 澄城县| 怀宁县| 工布江达县| 高要市| 正蓝旗| 封丘县| 马山县| 依安县| 吉安市| 新宁县| 丹棱县| 泸水县| 太白县| 景谷| 宁阳县|