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 =
请阅读: http : //satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/
我可以从你的信息得到的结论是: 你实习太多了 。 如果你真的需要实习这么多String来进行性能优化, 增加perm gen内存 ,但如果我是你, 我会先检查我是否真的需要这么多实习字符串。