真实生活,在Java中使用String.intern()的实际例子?

我已经看到很多原始的例子描述了String intern()的工作原理,但是我还没有看到一个可以从中受益的真实用例。

我梦寐以求的唯一情况是拥有一个接收大量请求的Web服务,由于僵化的架构,每个请求都非常相似。 通过intern()在这种情况下使用请求字段名称,可以显着减少内存消耗。

任何人都可以提供在生产环境中使用intern()并取得巨大成功的示例吗? 也许是一个流行的开源产品的例子?

编辑:我指的是手动实习,而不是字符串文字的保证实习等。

如果您有N字符串只能采用K不同的值,其中N远超过K ,则实习可能非常有用。 现在,不是将N字符串存储在内存中,而是只存储K

例如,您可能有一个由5位数组成的ID类型。 因此,只能有10^5不同的值。 假设您现在正在解析一个包含许多ID值引用/交叉引用的大型文档。 假设该文档总共有10^9引用(显然在文档的其他部分中重复了一些引用)。

因此在这种情况下N = 10^9K = 10^5 。 如果你没有实习字符串,你将在内存中存储10^9字符串,其中许多字符串是equals (通过Pigeonhole Principle )。 如果你intern()你在解析文档时得到的ID字符串,并且你没有保留对从文档中读取的未处理字符串的任何引用(因此它们可以被垃圾收集),那么你将永远不需要在内存中存储超过10^5字符串。

我们有一个生产系统,一次处理数百万条数据,其中许多都有字符串字段。 我们本来应该是实习生,但有一个错误意味着我们没有。 通过修复错误,我们避免了必须进行非常昂贵的(至少6位数,可能是7位)服务器升级。

实习将有益的示例涉及大量字符串,其中:

  • 字符串很可能在多个GC循环中存活,并且
  • 很可能会有很多字符串的多个副本。

典型示例涉及将文本拆分/解析为符号(单词,标识符,URI),然后将这些符号附加到长寿命数据结构中。 XML处理,编程语言编译和RDF / OWL三重存储作为内部可能有益的应用而浮现在脑海中。

但实习并非没有问题,特别是如果事实certificate上述假设不正确:

  • 用于保存实习字符串的池数据结构占用额外空间,
  • 实习需要时间,而且
  • interning不会阻止首先创建重复的字符串。

最后,通过增加需要跟踪和复制的对象数量,以及增加需要处理的弱引用数量,实习可能会增加GC开销。 这种开销的增加必须与有效实习产生的GC开销的减少相平衡。

不是一个完整的答案,而是额外的思考( 在这里找到 ):

因此,在这种情况下的主要好处是使用内部字符串的==运算符比使用equals()方法[对于非内化字符串]要快得多。 因此,如果您要比较字符串超过一次或三次,请使用intern()方法。

永远不要在用户提供的数据上使用实习生,因为这会导致拒绝服务攻击(因为intern()ed字符串永远不会被释放)。 您可以对用户提供的字符串进行validation,但是您再次完成了intern()所需的大部分工作。