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

如果我使用String.intern()来提高性能,因为我可以使用“==”来比较实习字符串,我会遇到垃圾收集问题吗? 实习字符串的垃圾收集机制与普通字符串有何不同?

实际上,这不是垃圾收集优化,而是字符串池优化。 当您调用String.intern() ,将初始String的引用替换为其基本引用(第一次遇到此字符串的引用,或者如果尚未知道此引用)。

但是,一旦您的字符串在应用程序中不再使用,它​​将成为垃圾收集器问题,因为实习字符串池是String类的静态成员,并且永远不会被垃圾回收。

根据经验,我认为从不使用这个实习方法并让编译器仅将它用于常量字符串,这些声明如下:

 String myString = "a constant that will be interned"; 

这是更好的,从某种意义上说它不会让你做错假设==当它不会时它可以工作。

此外,事实上String.equals底层调用==作为优化,使得它确保在引擎盖下使用实习字符串优化。 这是另一个证据== 永远不应该在字符串上使用。

String.intern()管理一个本机实现的内部池,它具有一些与GC相关的特殊function。 这是旧代码,但如果它是重新实现的,它将使用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()来比较字符串,您将活得更长久,更快乐。

本文提供了完整的答案。

在java 6中,字符串池驻留在PermGen中,因为java 7字符串池驻留在堆内存中。

手动实习的字符串将被垃圾收集。
如果卸载定义它们的类,则字符串文字将仅被垃圾收集。

字符串池是一个固定大小的HashMap,在java 6和早期版本的java 7中很小,但是自java 7u40以来增加到60013。
可以使用-XX:StringTableSize = 更改它,并使用-XX:+ PrintFlagsFinal java选项查看。

请阅读: http : //satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/

我可以从你的信息得到的结论是: 你实习太多了 。 如果你真的需要实习这么多String来进行性能优化, 增加perm gen内存 ,但如果我是你, 我会先检查我是否真的需要这么多实习字符串。