【问题标题】:Interned strings not in permgen?实习字符串不在 permgen 中?
【发布时间】:2013-04-30 10:41:54
【问题描述】:

我已经在我们正在运行的 Java 应用程序上运行了 jmap -heap 命令,这就是我得到的结果:

C:\Program Files\Java\jdk1.7.0_05\bin>jmap -heap 2384 正在附加到进程 ID 2384,请稍候... 调试器连接成功。 检测到服务器编译器。
JVM 版本为 23.1-b03

在新一代中使用并行线程。
使用线程局部对象分配。
并发 Mark-Sweep GC

堆配置:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
新大小 = 1310720 (1.25MB)
MaxNewSize = 17592186044415 MB
OldSize = 5439488 (5.1875MB)
新比率 = 2
幸存者比率 = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 201326592 (192.0MB)
G1HeapRegionSize = 0 (0.0MB)

堆使用:
新一代(伊甸园 + 1 个幸存者空间):
容量 = 228261888 (217.6875MB)
使用 = 203794000 (194.3531036376953MB)
免费 = 24467888 (23.334396362304688MB)
89.28078260703775% 已使用
伊甸园:
容量 = 202964992 (193.5625MB)
使用 = 198399360 (189.2083740234375MB)
免费 = 4565632 (4.3541259765625MB)
97.75053226913141% 已使用
来自太空:
容量 = 25296896 (24.125MB)
已使用 = 5394640 (5.1447296142578125MB)
免费 = 19902256 (18.980270385742188MB)
21.325304100550518% 已使用
去太空:
容量 = 25296896 (24.125MB)
已用 = 0 (0.0MB)
免费 = 25296896 (24.125MB)
0.0% 已使用
并发标记扫描生成:
容量 = 506445824 (482.984375MB)
使用 = 159479408 (152.09141540527344MB)
免费 = 346966416 (330.89295959472656MB)
31.489924576809226% 已使用
烫发一代:
容量 = 134217728 (128.0MB)
已使用 = 72157448 (68.81470489501953MB)
免费 = 62060280 (59.18529510498047MB)
53.76148819923401% 已使用

96874个interned Strings,占用89695496字节。

所以在 68mb 的 Permgen 中似乎有大约 89mb 的实习字符串。是否存在未存储在 Permgen 中的实习字符串?

【问题讨论】:

  • 你为什么会关心?我怀疑你是在试图进行微观管理。
  • @HotLicks - 因为我们有一个 permgen OOM 异常,我试图排除字符串实习。当然还有好奇心 :)

标签: java string permgen


【解决方案1】:

来自Java 7 release notes

在 JDK 7 中,interned 字符串不再分配在 Java 堆的永久代,而是分配在 Java 堆的主要部分(称为年轻和老 代),以及应用程序创建的其他对象。 此更改将导致更多数据驻留在主 Java 堆中, 并且永久代中的数据较少,因此可能需要堆 要调整的尺寸。大多数应用程序只会看到相对较小的 由于此更改,堆使用量的差异,但更大的应用程序 加载许多类或大量使用 String.intern() 方法 会看到更显着的差异。

【讨论】:

  • 请注意,这是 java 7 中的一个变化。另请参阅我的回答 here,其中包含一些有用的链接和指针,指向 java 8 中情况如何再次发生变化。
  • 谢谢!那么 Java 7 中 permgen 中唯一剩下的就是类加载器了?
  • 类加载器及其加载的类。我不知道从 Java 6 到 Java 7 的 PermGen 空间的其他变化。
  • 是的,我相信是这样...很好的类加载残余物,例如类结构、方法、类元信息等。我还没有分析过 java 7 JVM。此外,OOM 不会因此而得到解决……它们只会出现在堆空间中(例如,如果问题是内部字符串)。你要么加载的类多于你的永久空间可以容纳的数量,要么是类加载器泄漏。尝试使用 -XX:+TraceClassloading 和 -XX:+TraceClassUnloadin JAVA_OPTIONS 来跟踪类加载器行为。另外,请确保您的 -XX:MaxPermSize 是合理的。
  • 另外,您是否尝试过使用 VisualGC 仅查看 permgen 空间?如果您可以提供用例,您可以看到 permgen 被大量消耗的地方。我没有用 java 7 尝试过 VisualGC,但我不认为会出现问题,尽管我相信它现在已经被 VisualVM 吸收了。 VisualGC here 有一个有用的指南。
猜你喜欢
  • 2011-02-11
  • 2013-03-10
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
  • 2012-05-04
  • 2011-04-22
  • 1970-01-01
  • 2015-02-26
相关资源
最近更新 更多