日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java String的intern

發(fā)布時(shí)間:2024/4/17 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java String的intern 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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方法的性能

public class StringTest { 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的耗時(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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。