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

时间:2010-08-18 08:59:19

标签: java string permgen string-interning

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

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

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

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

5 个答案:

答案 0 :(得分:21)

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

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

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

答案 1 :(得分:1)

不是一个完整的答案,而是额外的思考(found here):

  

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

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

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

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

最后,通过增加需要跟踪和复制的对象数量,以及增加需要处理的弱引用数量,实现潜在会增加GC开销。这种间接费用的增加必须与有效实习导致的GC费用减少相平衡。

答案 4 :(得分:0)

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