短版:如果调用string.substring(n,m).intern(),字符串表是保留子字符串还是原始字符串?
...但我不确定这是一个正确的问题,所以这里是长版本:
我正在使用遗留 Java 代码 (PCGen),它通过将每个文件作为一个大字符串来解析文件,然后使用 String.split、.trim、.substring 和 StringTokenizer 将它们分解为令牌。这对于解析非常有效,因为这些方法都不会复制原始字符串,而是都指向共享 char[] 的一部分。
解析结束后,我想回收一些内存。只需要原始大字符串的几个小子字符串,但强引用阻止了大字符串被收集。后来我遭受了OOM,我相信部分是由于大量已解析文件的巨大堆影响。
new String(String)
我知道我可以通过(写时复制)修剪大字符串。而且我知道我可以通过 String.intern 减少字符串重复(这很重要,因为解析的文件中有很多冗余)。我需要同时使用两者来回收最大数量的堆,还是 .intern() 两者都做?阅读 OpenJDK7 热点源代码(hotspot/src/share/vm/classfile/symbolTable.cpp),看起来字符串表保留了整个字符串,并且根本没有修剪它的偏移量/长度。所以我想我需要制作一个新的字符串,然后实习这个结果。对?
综上所述,切换到流式解析器在内存方面将是一个巨大的胜利,但这对于短期而言变化太大了。