淺談Java String.intern()

簡書 占小狼
轉載請注明原創(chuàng)出處苍鲜,謝謝入热!

String.intern()原理

String.intern()是一個Native方法,底層調用C++的 StringTable::intern 方法拣宰,源碼注釋:當調用 intern 方法時遵绰,如果常量池中已經該字符串,則返回池中的字符串忠蝗;否則將此字符串添加到常量池中现横,并返回字符串的引用。

package com.ctrip.ttd.whywhy;
class Test {
    public static void main(String args[]) {
        String s1 = new StringBuilder().append("String").append("Test").toString();
        System.out.println(s1.intern() == s1);

        String s2 = new StringBuilder().append("ja").append("va").toString();
        System.out.println(s2.intern() == s2);
    }
}

在 JDK6 和 JDK7 中結果不一樣:

1阁最、JDK6的執(zhí)行結果:false false
對于這個結果很好理解戒祠。在JDK6中,常量池在永久代分配內存速种,永久代和Java堆的內存是物理隔離的姜盈,執(zhí)行intern方法時,如果常量池不存在該字符串配阵,虛擬機會在常量池中復制該字符串馏颂,并返回引用示血,所以需要謹慎使用intern方法,避免常量池中字符串過多饱亮,導致性能變慢矾芙,甚至發(fā)生PermGen內存溢出舍沙。

2近上、JDK7的執(zhí)行結果:true false
對于這個結果就有點懵了。在JDK7中拂铡,常量池已經在Java堆上分配內存壹无,執(zhí)行intern方法時,如果常量池已經存在該字符串感帅,則直接返回字符串引用斗锭,否則復制該字符串對象的引用到常量池中并返回,所以在JDK7中失球,可以重新考慮使用intern方法岖是,減少String對象所占的內存空間。


對于變量s1实苞,常量池中沒有 "StringTest" 字符串豺撑,s1.intern() 和 s1都是指向Java對象上的String對象。
對于變量s2黔牵,常量池中一開始就已經存在 "java" 字符串聪轿,所以 s2.intern() 返回常量池中 "java" 字符串的引用。

String.intern()性能

常量池底層使用StringTable數(shù)據(jù)結構保存字符串引用猾浦,實現(xiàn)和HashMap類似陆错,根據(jù)字符串的hashcode定位到對應的數(shù)組,遍歷鏈表查找字符串金赦,當字符串比較多時音瓷,會降低查詢效率。

在JDK6中夹抗,由于常量池在PermGen中绳慎,受到內存大小的限制,不建議使用該方法兔朦。
在JDK7偷线、8中,可以通過-XX:StringTableSize參數(shù)StringTable大小沽甥,下面通過幾個測試用例看看intern方法的性能声邦。

public class StringTest {
    public static void main(String[] args) {
        System.out.println(cost(1000000));
    }

    public static long cost(int num) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < num; i++) {
            String.valueOf(i).intern();
        }
        return System.currentTimeMillis() - start;
    }
}

執(zhí)行一百萬次intern()方法,不同StringTableSize的耗時情況如下:
1摆舟、-XX:StringTableSize=1009亥曹, 平均耗時23000ms邓了;
2、-XX:StringTableSize=10009媳瞪, 平均耗時2200ms骗炉;
3、-XX:StringTableSize=100009蛇受, 平均耗時200ms句葵;
4、默認情況下兢仰,平均耗時400ms乍丈;

在默認StringTableSize下,執(zhí)行不同次intern()方法的耗時情況如下:
1把将、一萬次轻专,平均耗時5ms;
2察蹲、十萬次请垛,平均耗時25ms;
3洽议、五十萬次宗收,平均耗時130ms;
4绞铃、一百萬次镜雨,平均耗時400ms;
5儿捧、五百萬次荚坞,平均耗時5000ms;
6菲盾、一千萬次颓影,平均耗時15000ms;

從這些測試數(shù)據(jù)可以看出懒鉴,盡管在Java 7以上對intern()做了細致的優(yōu)化诡挂,但其耗時仍然很顯著,如果無限制的使用intern()方法临谱,將導致系統(tǒng)性能下降璃俗,不過可以將有限值的字符串放入常量池,提高內存利用率悉默,所以intern()方法是一把雙刃劍城豁。

END。
我是占小狼抄课。
在魔都艱苦奮斗唱星,白天是上班族雳旅,晚上是知識服務工作者。
如果讀完覺得有收獲的話间聊,記得關注和點贊哦攒盈。
非要打賞的話,我也是不會拒絕的哎榴。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末型豁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叹话,更是在濱河造成了極大的恐慌偷遗,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驼壶,死亡現(xiàn)場離奇詭異,居然都是意外死亡喉酌,警方通過查閱死者的電腦和手機热凹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泪电,“玉大人般妙,你說我怎么就攤上這事∠嗨伲” “怎么了碟渺?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長突诬。 經常有香客問我苫拍,道長,這世上最難降的妖魔是什么旺隙? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任绒极,我火速辦了婚禮,結果婚禮上蔬捷,老公的妹妹穿的比我還像新娘垄提。我一直安慰自己,他們只是感情好周拐,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布铡俐。 她就那樣靜靜地躺著,像睡著了一般妥粟。 火紅的嫁衣襯著肌膚如雪审丘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天罕容,我揣著相機與錄音备恤,去河邊找鬼稿饰。 笑死,一個胖子當著我的面吹牛露泊,可吹牛的內容都是我干的喉镰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼惭笑,長吁一口氣:“原來是場噩夢啊……” “哼侣姆!你這毒婦竟也來了?” 一聲冷哼從身側響起沉噩,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捺宗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后川蒙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚜厉,經...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年畜眨,在試婚紗的時候發(fā)現(xiàn)自己被綠了昼牛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡康聂,死狀恐怖贰健,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情恬汁,我是刑警寧澤伶椿,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站氓侧,受9級特大地震影響脊另,放射性物質發(fā)生泄漏。R本人自食惡果不足惜甘苍,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一尝蠕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧载庭,春花似錦看彼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至顽铸,卻和暖如春茁计,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谓松。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工星压, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留践剂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓娜膘,卻偏偏與公主長得像逊脯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子竣贪,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內容

  • String.intern()原理String.intern()是一個Native方法军洼,底層調用c++的Strin...
    水欣閱讀 447評論 0 1
  • ??需要說明的一點是,這篇文章是以《深入理解Java虛擬機》第二版這本書為基礎的演怎,這里假設大家已經了解了JVM的運...
    Geeks_Liu閱讀 14,023評論 5 44
  • 前言 最近一直在關注“故障排查”的相關知識,首先著手的是OOM的異常畏纲。OOM異常通常會有Perm區(qū)的OOM(jav...
    LNAmp閱讀 2,596評論 0 6
  • 字符串操作是最常見的操作扇住。在Java中,往往使用String類來進行各種字符串操作盗胀。而對于String這個類,其實...
    zcliu閱讀 178評論 0 0
  • 我們的消息記錄從我上一次锄贼,再上一次的生日開始票灰。 你在QQ上祝我生日快樂,而且還講了一大堆溢美之詞……而我實在是有點...
    洋洋aaa閱讀 190評論 0 0