为什么PermGen空间越来越大?

Pab*_*dez 17 java memory-leaks memory-management

我已经阅读了一些文章,我理解了以下内容(如果我错了,请纠正我和/或编辑问题):

java堆是这样分段的:

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

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

编辑:如其他用户所述,PermGen不是所谓的区域的一部分 heap

  • PermGen:这个区域充满了你的app类元数据和许多其他不依赖于应用程序使用的东西.

所以,知道这一点......为什么我的PermGen空间会在应用程序负载过重时增长?对于我之前所说的这个空间不应该在应用程序加载的情况下逐渐填充,但正如我在开始时所说的那样,我可能错误地做了一些假设.

事实上,如果PermGen空间正在增长,有没有一种垃圾收集或重置方式?

Jos*_*non 19

实际上,在Sun的JVM中,永久生成(PermGen)与堆完全分离.你确定你不是在看Tenured Generation吗?如果你的永久性一代继续增长,那将是可疑的.

如果你的权力不断增长,那么这是一个难以挖掘的领域.通常,它应该在第一次加载新类时增长(并且可能某些反射的使用也可能导致这种情况).Interned字符串也存储在perm gen中.

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

来自Sun的JConsole指南(可以让你查看这些池的大小):

对于HotSpot Java VM,串行垃圾收集的内存池如下.

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


Joh*_*fer 6

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

  • 自定义类加载器,在加载新类之后不会小心地释放旧类.
  • 多次重新部署应用程序后,PermGen中剩余的类(在Dev中比Prod更常见)
  • 大量使用Proxy类,它们是在运行时合成创建的.当单个类定义可以重用于多个实例时,可以轻松创建新的Proxy类.


小智 6

这是调试中比较烦人的问题之一.有很多原因你可以看到越来越多的permgen使用.以下是我发现的两个链接,它们既可以了解泄漏的发生方式,也可以跟踪导致泄漏的原因.

http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html