Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 8字符串重复数据消除与String.intern()的比较_Java_String_Jvm Hotspot_Deduplication - Fatal编程技术网

Java 8字符串重复数据消除与String.intern()的比较

Java 8字符串重复数据消除与String.intern()的比较,java,string,jvm-hotspot,deduplication,Java,String,Jvm Hotspot,Deduplication,我正在阅读Java 8 update 20中关于字符串重复数据消除()的功能,但我不确定这是否会使String.intern()过时 我知道这个JVM功能需要G1垃圾收集器,这对很多人来说可能不是一个选项,但是假设有人使用G1GC,JVM自动执行重复数据消除与手动执行intern字符串有什么区别/优势/劣势(一个明显的优点是不必通过调用intern())来污染代码。) 考虑到Oracle可能会使用此功能使G1GC成为java 9中的默认GC,这一点尤其有趣。如果您有1000个不同的字符串对象,所

我正在阅读Java 8 update 20中关于字符串重复数据消除()的功能,但我不确定这是否会使
String.intern()
过时

我知道这个JVM功能需要G1垃圾收集器,这对很多人来说可能不是一个选项,但是假设有人使用G1GC,JVM自动执行重复数据消除与手动执行
intern
字符串有什么区别/优势/劣势
(一个明显的优点是不必通过调用
intern()
)来污染代码。)


考虑到Oracle可能会使用此功能使G1GC成为java 9中的默认GC,这一点尤其有趣。如果您有1000个不同的字符串对象,所有对象都具有相同的内容,JVM可以使它们在内部共享相同的
char[]
。但是,您仍然有1000个不同的
String
对象

使用
intern()
,您将只有一个
String
对象。因此,如果您关心内存节省,
intern()
会更好。它将节省空间和GC时间


然而,上次我听说,
intern()
的性能并没有那么好。您最好拥有自己的字符串缓存,甚至使用
ConcurrentHashMap
…但您需要对其进行基准测试以确保。

我想介绍另一个与目标受众相关的决策因素:

  • 对于一个系统集成商来说,系统由许多不同的库/框架组成,其容量很低,无法影响这些库的内部开发,如果内存存在问题,StringDuplication可能是一个快速的赢家。它会影响JVM中的所有字符串,但G1只会使用空闲时间来完成。在进行重复数据消除时,您甚至可能会进行调整通过使用另一个参数(StringDeduplicationGetThreshold)计算重复数据
  • 对于分析自己代码的开发人员来说,String.intern可能更有趣。需要仔细检查域模型,以确定是否调用intern以及何时调用。根据经验,当您知道字符串将包含一组有限的值时,可以使用intern,例如枚举集(即国家名称、月份、星期几…)

作为评论参考,请参见:。这是一篇非常有见地的参考文章,我学到了很多东西,但是我不确定它的结论是否一定是“一刀切”。每个方面都取决于您自己应用程序的需要-强烈建议对实际输入数据进行测量

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

  • 您是否可以完全控制GC的选择?例如,在GUI应用程序中,使用串行GC仍然有很好的理由。(该过程的总内存占用量要低得多-对于一个中等复杂的应用程序,想想400 MB vs~1 GB,并且更愿意释放内存,例如在使用率出现短暂峰值后)。因此,您可以选择该选项,或者让您的用户选择。(如果堆仍然很小,那么暂停应该不是什么大问题)

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

第二个考虑(根据@ZhongYu的回答)是
String.intern
可以对
String
对象本身进行重复数据消除,而G1GC必须只能对其私有
char[]
字段进行重复数据消除

第三个考虑因素可能是CPU使用情况,比如对笔记本电脑电池寿命的影响可能会引起用户的关注。G1GC将运行一个额外的线程,专门用于消除堆的重复。例如,我在运行Eclipse时使用了这个线程,发现它在启动后会导致CPU活动的初始阶段增加(想想1-2分钟)但是,它解决了一个较小的堆“正在使用”,并且没有明显的CPU开销(仅仅是任务管理器的眼珠)或此后的速度减慢。因此,我认为一定比例的CPU核心将用于重复数据消除(在?之后?)高内存波动期间。(当然,如果到处调用String.intern,可能会有相当的开销,它也会以串行方式运行,但是…)

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

  • 真正影响堆的长期使用,
  • 创建高比例的重复字符串
通过有选择地使用
String.intern
,代码的其他部分(可能创建临时或半临时字符串)不会为此付出代价

最后,一个用于Guava实用程序的快速插头:,它:

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


您也可以将其用于字符串。内存可能是(并且应该是)你的最高性能关注,所以这可能不经常适用:但是当你需要挤压某个热点区域的每一个速度,我的经验是,基于java的弱引用HasMeP解决方案运行的速度比JVM C++实现的代码<> String。,即使在优化了jvm选项之后。(还有一个好处:你不需要调整jvm选项以适应不同的输入。)

——但不管怎样,结论总是一样的:你.Should.Not.Care.sorry,不应该关心什么?关于使用哪一个(意味着它们是等效的)或关于新功能(意味着它没有那么有用)??含义:不用再想就可以使用
String
类。好问题。这些特性添加到JVM中是一个提示,提示开发人员将重点放在编码而不是内存管理上。您不应该使用
String.intern()
System.gc()
——让虚拟机完成它的工作。@DavidConrad在完整的引用中克努斯实际上量化了他的建议:“我们应该忘记小效率,比如说