簡體   English   中英

String.intern()的垃圾收集行為

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM