字符串是不可变的。当我宣布:
String a = "abc";
String a1 = "abc";
两个对象都指向相同的位置。那我怎么能破坏这个" abc"字符串池的引用?
我的用例是我正在开发一个内存较少的硬件应用程序,为此,我需要清除String池中的引用以节省内存。
答案 0 :(得分:6)
不,通常您不能手动“从Java中销毁String池中的引用”。
我认为你瞄准它的主要原因是避免内存不足错误。在Java 6天中,所有实习字符串都存储在PermGen中 - 堆的固定大小部分主要用于存储加载的类和字符串池。除了显式实现的字符串外,PermGen字符串池还包含程序中先前使用的所有文字字符串。 Java 6中字符串池的最大问题是它的位置--PermGen。 PermGen 具有固定大小,无法在运行时展开。您可以使用 -XX:MaxPermSize = N 选项进行设置。这会导致内存泄漏和内存不足错误。
在Java 7中 - 字符串池被重新定位到堆。这意味着您不再受限于单独的固定大小的内存区域。所有字符串现在都位于堆中,与大多数其他普通对象一样。
您还可以通过配置 -XX:StringTableSize = N 来增加字符串池大小。 如果您不确定字符串池的使用情况,请尝试 - XX:+ PrintStringTableStatistics JVM参数。它将在程序终止时打印字符串池使用情况。
在JDK中,还有一个名为jmap 的工具,可用于查找应用程序中的实习字符串数。
jmap -heap process_id
例如:
jmap -heap 18974
与其他输出一起,此命令还输出实习字符串的数量以及它们占用的空间“ xxxxxx interned Strings占用xxxxxx字节。”
String池中对象的垃圾收集的规则与其他字符串或任何其他对象相同。但事实上,对应于String文字的String对象大多数总是可以访问的,因为在使用该文字的每个方法的代码中都存在对字符串对象的隐式引用,因此通常它们不是垃圾收集的候选者。 然而,这并非总是如此。如果文字是在动态加载的类中定义的(例如,使用Class.forName(...)),则可以安排卸载类。如果发生这种情况,那么文字的String对象将无法访问,并且当包含实习字符串的堆得到GC时将被回收。