24

我已经看到许多描述 String intern()'ing 如何工作的原始示例,但我还没有看到可以从中受益的真实用例。

我能想到的唯一情况是拥有一个接收大量请求的 Web 服务,由于严格的模式,每个请求在性质上都非常相似。在这种情况下,通过对请求字段名称进行实习(),可以显着减少内存消耗。

谁能提供一个在生产环境中使用 intern() 并取得巨大成功的例子?也许是流行的开源产品中的一个例子?

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

4

5 回答 5

21

如果您的N字符串只能采用K不同的值,并且N远远超过K. 现在,N您不再将字符串存储在内存中,而是最多存储K.

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

所以在这种情况下N = 10^9K = 10^5如果您没有实习字符串,您将把10^9字符串存储在内存中,其中很多字符串都在内存中equals(通过Pigeonhole 原则)。如果您在解析文档时获得intern()ID字符串,并且您没有保留对从文档中读取的非内部字符串的任何引用(因此它们可以被垃圾收集),那么您将永远不需要存储超过10^5字符串在记忆中。

于 2010-08-18T09:54:08.277 回答
1

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

因此,在这种情况下,主要的好处是使用==操作符处理内部化字符串比使用equals()方法 [for not internalized Strings] 快得多。因此,intern()如果您要比较字符串超过一到三次,请使用该方法。

于 2010-08-18T09:07:18.873 回答
1

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

于 2010-08-18T09:11:41.967 回答
1

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

  • 字符串可能会在多个 GC 周期中存活,并且
  • 大部分字符串可能有多个副本。

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

但是实习也不是没有问题,尤其是如果上面的假设是不正确的:

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

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

于 2010-08-18T10:36:33.667 回答
0

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

于 2010-08-18T09:28:00.163 回答