字符串是不可变的.当我宣布:
String a = "abc";
String a1 = "abc";
Run Code Online (Sandbox Code Playgroud)
两个对象都指向相同的位置.那么如何从String池中销毁这个"abc"引用呢?
我的用例是我正在开发一个内存较少的硬件应用程序,为此,我需要清除String池中的引用以节省内存.
不,通常您不能手动"从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
Run Code Online (Sandbox Code Playgroud)
例如:
jmap -heap 18974
Run Code Online (Sandbox Code Playgroud)
与其他输出一起,此命令还输出多个实习字符串以及它们占用的空间" xxxxxx interned Strings占用xxxxxx字节".
将在字符串池中对象的垃圾收集规则是一样的其他字符串或任何其他对象.但事实上,对应于String文字的String对象大多数总是可以访问的,因为在使用该文字的每个方法的代码中都存在对字符串对象的隐式引用,因此通常它们不是垃圾收集的候选者.然而,这并非总是如此.如果文字是在动态加载的类中定义的(例如,使用Class.forName(...)),则可以安排卸载类.如果发生这种情况,那么文字的String对象将无法访问,并且当包含实习字符串的堆得到GC时将被回收.