我正在阅读有关字符串重复数据删除(more info)的Java 8更新20中的功能,但我不确定这是否会使String.intern()
过时。
我知道这个JVM功能需要G1垃圾收集器,这对许多人来说可能不是一个选项,但假设有人使用G1GC,是否存在JVM自动重复数据删除的差异/优势/劣势vs手动必须intern
你的字符串(一个明显的优点是不必通过调用intern()
污染你的代码)?
考虑到Oracle可能会将G1GC作为java 9中的默认GC
,这一点尤其有趣答案 0 :(得分:10)
使用此功能,如果您有1000个不同的String对象,所有对象具有相同的内容"abc"
,JVM可以使它们在内部共享相同的char[]
。但是,您仍然有1000个不同的String
个对象。
使用intern()
,您只有一个String
个对象。因此,如果您关心节省内存,intern()
会更好。它将节省空间和GC时间。
然而,上次我听到intern()
的表现并不是那么好。拥有自己的字符串缓存可能会更好,即使使用ConcurrentHashMap
...但您需要对其进行基准测试以确保。
答案 1 :(得分:4)
作为评论参考,请参阅:http://java-performance.info/string-intern-in-java-6-7-8/。这是非常有见地的参考,我学到了很多,但我不确定它的结论是否“一刀切”。每个方面都取决于您自己的应用程序的需求 - 强烈建议测量实际输入数据!
主要因素可能取决于您控制的内容:
您是否可以完全控制GC的选择?例如,在GUI应用程序中,使用Serial GC仍然有很强的理由。 (该过程的总内存占用空间要低得多 - 对于中等复杂的应用程序,请考虑400 MB与~1 GB,并且更愿意释放内存,例如在使用率出现短暂高峰后)。所以你可以选择它或给你的用户选择。 (如果堆仍然很小,暂停不应该是一个大问题。)
您是否可以完全控制代码? G1GC选项非常适合您无法编辑的第三方库(和应用程序!)。
第二个考虑因素(根据@ ZhongYu的回答)是String.intern
可以对String
个对象本身进行重复数据删除,而G1GC必然只能去除它们的私有char[]
字段。
第三个考虑因素可能是CPU使用率,例如,如果您的用户可能会对笔记本电脑的电池寿命产生影响。 G1GC将运行一个专门用于重复堆栈的额外线程。例如,我使用它来运行Eclipse并发现它在启动后导致初始阶段的CPU活动增加(想想1 - 2分钟)但它确定在一个较小的堆“使用中”并且没有明显的(只是眼睛 - 对任务管理器进行计算)此后CPU开销或减速。所以我想在CPU内核的某个百分比将被用于重复数据删除(在?之后?)高内存流失期间。 (当然,如果你调用String.intern 无处不在,也可能有相似的开销,这也会串行运行,但随后......)
您可能不需要在任何地方进行字符串重复数据删除。可能只有某些代码区域:
有选择地使用String.intern
,代码的其他部分(可能会创建临时或半临时字符串)不会付出代价。
最后,快速插入Guava实用程序:Interner,其中:
为
String.intern()
提供与其他不可变类型相同的行为
您也可以将其用于字符串。内存可能(并且应该)是您最关注的性能问题,因此这可能不经常适用:但是当您需要从某些热点区域挤出每一滴速度时,我的经验是基于Java的弱引用即使在调整jvm选项之后,HashMap解决方案也会比JVM的String.intern()
C ++实现略微但一致地运行得更快。 (并且奖励:您不需要调整JVM选项以扩展到不同的输入。)
答案 2 :(得分:2)
我想介绍另一个关于目标受众的决策因素: