Java 8 String deduduction vs. String.intern()

2022-09-02 13:22:43

我正在阅读有关Java 8 update 20中字符串重复数据删除的功能(更多信息),但我不确定这是否基本上过时了。String.intern()

我知道这个JVM功能需要G1垃圾回收器,这对许多人来说可能不是一个选择,但是假设一个人使用G1GC,JVM完成的自动重复数据删除与手动必须实习字符串有什么区别/优点/缺点(一个明显的是不必通过调用)污染代码的优点?intern()

考虑到Oracle可能会使G1GC成为java 9中的默认GC,这一点特别有趣。


答案 1

使用此功能,如果您有1000个不同的String对象,并且都具有相同的内容,JVM可以使它们在内部共享相同的内容。但是,您仍然有 1000 个不同的对象。"abc"char[]String

使用 ,您将只有一个对象。因此,如果节省内存是您关心的问题,那就更好了。它将节省空间,以及GC时间。intern()Stringintern()

但是,上次我听说,性能并不是那么好。通过拥有自己的字符串缓存,即使使用...但你需要对它进行基准测试以确保。intern()ConcurrentHashMap


答案 2

作为注释引用,请参阅:http://java-performance.info/string-intern-in-java-6-7-8/。这是非常有见地的参考,我学到了很多东西,但我不确定它的结论是否一定是“一刀切”。。每个方面都取决于您自己应用的需求 - 强烈建议对真实的输入数据进行测量!

主要因素可能取决于您控制的内容:

  • 您是否可以完全控制GC的选择?例如,在GUI应用程序中,使用串行GC仍然有很强的理由。(该过程的总内存占用量要低得多 - 对于中等复杂的应用程序,考虑400 MB与~1 GB,并且更愿意释放内存,例如,在使用量短暂高峰之后)。因此,您可以选择它或为用户提供选项。(如果堆仍然很小,暂停应该没什么大不了的)。

  • 您是否完全控制代码?G1GC选项非常适合您无法编辑的第三方库(和应用程序!

第二个考虑因素(根据@ZhongYu的答案)是可以对对象本身进行重复数据删除,而G1GC必然只能删除其私有字段的重复数据。String.internStringchar[]

第三个考虑因素可能是CPU使用率,例如您的用户是否可能担心对笔记本电脑电池寿命的影响。G1GC 将运行一个专用于对堆进行重复数据消除的额外线程。例如,我用它来运行Eclipse,发现它在启动后(想想1-2分钟)导致CPU活动增加的初始时期,但它落在一个较小的堆“使用中”,并且没有明显的(只是盯着任务管理器)CPU开销或此后减速。因此,我想象一定比例的 CPU 内核将用于重复数据消除(在?之后?)高内存变动期。(当然,如果你在任何地方调用String.intern,可能会有类似的开销,它也将串行运行,但是......)

您可能不需要到处都进行字符串重复数据消除。可能只有某些代码区域:

  • 真正影响长期堆使用,以及
  • 创建高比例的重复字符串

通过有选择地使用,代码的其他部分(可能会创建临时或半临时字符串)不会付出代价。String.intern

最后,番石榴实用程序的快速插入:Interner,它:

提供与其他不可变类型等效的行为String.intern()

您也可以将其用于字符串。内存可能是(并且应该是)你最关心的性能问题,所以这可能并不经常适用:但是,当你需要从某个热点区域挤出每一滴速度时,我的经验是,基于Java的弱引用HashMap解决方案确实运行得比JVM C++实现略快,但始终比JVM的实现快,即使在调整jvm选项之后也是如此。(还有好处:您无需调整 JVM 选项即可扩展到不同的输入。String.intern()