为什么彼尔姆根的空间在增长?

2022-09-03 00:10:13

我读过几篇文章,我理解了以下内容(如果我错了,请纠正我和/或编辑问题):

Java 堆是这样分段的:

  • 年轻一代:创建的对象去这里,这部分经常被廉价地垃圾收集

  • 老一代:在年轻一代的垃圾回收中幸存下来的对象来到这里,这个区域的垃圾收集频率较低,并且使用对CPU要求更高的进程/算法(我相信它被称为标记扫描)

编辑:正如另一位用户所说,PermGen不是称为区域的一部分heap

  • PermGen:此区域填充了应用类元数据和许多其他不依赖于应用程序使用情况的内容。

所以,知道这一点...为什么当应用程序负载过重时,我的 PermGen 空间会增长?对于我之前所说的,尽管应用程序加载,但这个空间不应该增量填充,但正如我在开始时所说,我对一些假设可能是错误的。

事实上,如果PermGen空间正在增长,是否有一种方法可以进行垃圾回收或重置它?


答案 1

实际上,在Sun的JVM永久生成(PermGen)中,永久生成与堆完全分开。你确定你不是在看终身制的一代吗?如果你的永久一代继续增长,那确实是可疑的。

如果你的烫发基因在不断增长,这是一个很难挖掘的领域。通常,当第一次加载新类时,它应该会增长(并且反射的某些用途也可能导致这种情况)。被拘禁的字符串也存储在烫发中。

如果您碰巧在 Solaris 上,则可以使用 jmap -permstat 转储 perm gen 统计信息,但该选项在 Windows(以及可能的其他平台)上似乎不可用。以下是有关 java 6 的 jmap 的文档

来自Sun关于JConsole的指南(这将允许您查看这些池的大小):

对于 HotSpot Java VM,用于串行垃圾回收的内存池如下所示。

  • 伊甸园空间(堆):最初为大多数对象分配内存的池。
  • 幸存者空间(堆):包含在伊甸园空间的垃圾回收中幸存下来的物体的池。
  • 终身世代(堆):包含幸存者空间中已存在一段时间的对象的池。
  • 永久生成(非堆):包含虚拟机本身的所有反射数据(如类和方法对象)的池。对于使用类数据共享的 Java VM,这一代分为只读和读写区域。
  • 代码缓存(非堆):HotSpot Java VM 还包括一个代码缓存,其中包含用于编译和存储本机代码的内存。

答案 2

我见过的最常见的原因是:

  • 自定义类装入器,在加载新类后不会小心释放旧类。
  • 多次重新部署应用程序后,PermGen 中剩余的类(在 Dev 中比在 Prod 中更常见)
  • 大量使用代理类,这些类是在运行时综合创建的。当单个类定义可以重用于多个实例时,很容易创建新的代理类。

推荐