[英]Garbage collection behaviour for String.intern()
如果我使用String.intern()來提高性能,因為我可以使用“==”來比較實習字符串,我會遇到垃圾收集問題嗎? 實習字符串的垃圾收集機制與普通字符串有何不同?
String.intern()
管理一個內部的本機實現池,它具有一些特殊的GC相關功能。 這是舊代碼,但如果它是重新實現的,它將使用java.util.WeakHashMap
。 弱引用是一種保持指向對象的指針而不阻止它被收集的方法。 對於統一池,如實習字符串,這是正確的事情。
可以使用以下Java代碼演示可以使用垃圾收集的實際字符串:
public class InternedStringsAreCollected {
public static void main(String[] args)
{
for (int i = 0; i < 30; i ++) {
foo();
System.gc();
}
}
private static void foo()
{
char[] tc = new char[10];
for (int i = 0; i < tc.length; i ++)
tc[i] = (char)(i * 136757);
String s = new String(tc).intern();
System.out.println(System.identityHashCode(s));
}
}
此代碼創建相同字符串的30倍,每次實習。 此外,它使用System.identityHashCode()
來顯示在該實習字符串上返回的哈希代碼Object.hashCode()
。 運行時,此代碼打印出不同的整數值,這意味着每次都不會獲得相同的實例。
無論如何,有點不鼓勵使用String.intern()
。 它是一個共享的靜態池,這意味着它很容易成為多核系統的瓶頸。 使用String.equals()
來比較字符串,您將活得更長久,更快樂。
實際上,這不是垃圾收集優化,而是字符串池優化。 當您調用String.intern()
,您將初始String的引用替換為其基本引用(第一次遇到此字符串的引用,或者如果尚未知道此引用)。
但是,一旦您的字符串在應用程序中不再使用,它將成為垃圾收集器問題,因為實習字符串池是String類的靜態成員,並且永遠不會被垃圾回收。
根據經驗,我認為從不使用這個實習方法並讓編譯器僅將它用於常量字符串,這些聲明如下:
String myString = "a constant that will be interned";
這是更好的,從某種意義上說,它不會讓你做錯誤的假設==
當它不會時可以工作。
此外,事實上String.equals
底層調用==
作為優化,使得它確保在引擎蓋下使用實習字符串優化。 這是另一個證據==
永遠不應該在字符串上使用。
本文提供了完整的答案。
在java 6中,字符串池駐留在PermGen中,因為java 7字符串池駐留在堆內存中。
手動實習的字符串將被垃圾收集。
如果卸載定義它們的類,則字符串文字將僅被垃圾收集。
字符串池是一個固定大小的HashMap,在java 6和早期版本的java 7中很小,但自java 7u40以來增加到60013。
可以使用-XX:StringTableSize = <new size>更改它,並使用-XX:+ PrintFlagsFinal java選項查看。
請閱讀: http : //satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/
我可以從你的信息得到的結論是: 你實習太多了 。 如果你真的需要為實現性能優化實習這么多String, 增加perm gen內存 ,但如果我是你, 我會先檢查我是否真的需要這么多實習字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.