为什么PermGen空间不断增长?

问题描述:

我读了几篇文章,我明白以下内容(请指正和/或编辑的问题,如果我错了):为什么PermGen空间不断增长?

Java堆分割这样的:

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

  • 老一代:在年轻一代的垃圾收集生存的对象去这里,这个地区是垃圾收集较少,并使用更多的CPU要求过程/算法(我相信这就是所谓的标记 - 清除)

编辑:由另一个用户说,PermGen的不是区域称为heap

  • PermGen的一部分:这个地区充满你的应用程序类的元数据和许多其他的东西不依赖于应用程序的使用。

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

事实上,如果PermGen的空间越来越大,有没有垃圾的方式收集或重置?

+0

请问您是否可以进一步澄清您的烫发电池正在增长时发生了什么?你如何看待你的烫发器正在增长? – 2010-01-12 19:54:32

事实上,在Sun的JVM永久代(PermGen的)是从堆完全分开。你确定你没有看着Tenured Generation吗?如果你的永久代继续增长,这将是可疑的。

如果您的烫发产品不断增长,这是一个难以深入的领域。一般来说,它应该在第一次加载新类时增长(并且反射的某些用途也可能导致这种情况)。 Interned字符串也存储在perm gen中。

如果您碰巧在Solaris上,可以使用jmap -permstat转储出perm gen统计信息,但该选项似乎不适用于Windows(以及其他平台)。这里是the documentation on jmap for Java 6

从Sun的guide on JConsole(这将让你查看这些池的大小):

有关,以HotSpot Java虚拟机,存储 池串行垃圾收集 有以下几种。

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

你对类加载器链做了些什么样的事情吗?你在一串字符串上打电话intern()

+0

不,应用程序的“沉重部分”在于反序列化大对象图,但该图主要是内部带有字符串的HashMaps。也许这叫'实习生'? – 2010-01-12 19:35:05

+2

没有。HashMap不会调用intern()。 – 2010-01-12 19:37:55

当您操作类加载器时,这是一个非常常见的问题。当您重新部署hibernate/cglib时,这在Java EE应用程序中看到很多。欲了解更多信息请查看

http://opensource.atlassian.com/confluence/spring/display/DISC/Memory+leak+-+classloader+won%27t+let+go

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

  • 自定义类加载器在加载换新后不仔细腾出旧的课程。
  • 多次重新部署应用程序后在PermGen中保留的类(在Dev中比Dev更常见)
  • 大量使用代理类,它们是在运行时合成创建的。当一个类定义可以重复用于多个实例时,创建新的代理类很容易。

这是一个比较烦人的调试问题。有很多原因可以让你看到越来越多的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

+0

+1的真棒链接。上周我偶然发现了其中一个,但之后失去了联系。 – 2010-01-12 20:29:11

如果您正在使用的Java EE应用程序时它可能是一个类加载器泄漏。

您可能会发现下面的附加链接有用:

http://www.zeroturnaround.com/blog/rjc201/

http://www.ibm.com/developerworks/java/library/j-dclp3/index.html

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

  1. Java类加载
  2. JAXBContext.newInstance
  3. String.intern()