Java String的intern
String.intern()原理
String.intern()是一個(gè)Native方法,底層調(diào)用C++的 StringTable::intern 方法,源碼注釋:當(dāng)調(diào)用 intern 方法時(shí),如果常量池中已經(jīng)該字符串,則返回池中的字符串;否則將此字符串添加到常量池中,并返回字符串的引用。
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 中結(jié)果不一樣:
1、JDK6的執(zhí)行結(jié)果:false false
對于這個(gè)結(jié)果很好理解。在JDK6中,常量池在永久代分配內(nèi)存,永久代和Java堆的內(nèi)存是物理隔離的,執(zhí)行intern方法時(shí),如果常量池不存在該字符串,虛擬機(jī)會(huì)在常量池中復(fù)制該字符串,并返回引用,所以需要謹(jǐn)慎使用intern方法,避免常量池中字符串過多,導(dǎo)致性能變慢,甚至發(fā)生PermGen內(nèi)存溢出。
2、JDK7的執(zhí)行結(jié)果:true false
對于這個(gè)結(jié)果就有點(diǎn)懵了。在JDK7中,常量池已經(jīng)在Java堆上分配內(nèi)存,執(zhí)行intern方法時(shí),如果常量池已經(jīng)存在該字符串,則直接返回字符串引用,否則復(fù)制該字符串對象的引用到常量池中并返回,所以在JDK7中,可以重新考慮使用intern方法,減少String對象所占的內(nèi)存空間。
對于變量s1,常量池中沒有 “StringTest” 字符串,s1.intern() 和 s1都是指向Java對象上的String對象。
對于變量s2,常量池中一開始就已經(jīng)存在 “java” 字符串,所以 s2.intern() 返回常量池中 “java” 字符串的引用。
String.intern()性能
常量池底層使用StringTable數(shù)據(jù)結(jié)構(gòu)保存字符串引用,實(shí)現(xiàn)和HashMap類似,根據(jù)字符串的hashcode定位到對應(yīng)的數(shù)組,遍歷鏈表查找字符串,當(dāng)字符串比較多時(shí),會(huì)降低查詢效率。
在JDK6中,由于常量池在PermGen中,受到內(nèi)存大小的限制,不建議使用該方法。
在JDK7、8中,可以通過-XX:StringTableSize參數(shù)StringTable大小,下面通過幾個(gè)測試用例看看intern方法的性能
執(zhí)行一百萬次intern()方法,不同StringTableSize的耗時(shí)情況如下:
1、-XX:StringTableSize=1009, 平均耗時(shí)23000ms;
2、-XX:StringTableSize=10009, 平均耗時(shí)2200ms;
3、-XX:StringTableSize=100009, 平均耗時(shí)200ms;
4、默認(rèn)情況下,平均耗時(shí)400ms;
在默認(rèn)StringTableSize下,執(zhí)行不同次intern()方法的耗時(shí)情況如下:
1、一萬次,平均耗時(shí)5ms;
2、十萬次,平均耗時(shí)25ms;
3、五十萬次,平均耗時(shí)130ms;
4、一百萬次,平均耗時(shí)400ms;
5、五百萬次,平均耗時(shí)5000ms;
6、一千萬次,平均耗時(shí)15000ms;
從這些測試數(shù)據(jù)可以看出,盡管在Java 7以上對intern()做了細(xì)致的優(yōu)化,但其耗時(shí)仍然很顯著,如果無限制的使用intern()方法,將導(dǎo)致系統(tǒng)性能下降,不過可以將有限值的字符串放入常量池,提高內(nèi)存利用率,所以intern()方法是一把雙刃劍。
轉(zhuǎn)載于:https://blog.51cto.com/12666319/2114724
總結(jié)
以上是生活随笔為你收集整理的Java String的intern的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理解Python中的类对象、实例对象、属
- 下一篇: Kotlin 喧嚣过后,谈谈 Java