Java 为什么永磁空间在增长?

Java 为什么永磁空间在增长?,java,memory-leaks,memory-management,Java,Memory Leaks,Memory Management,我读过几篇文章,我理解以下内容(如果我错了,请纠正我和/或编辑问题): java堆的分段如下所示: 年轻一代:创建的对象放在这里,这部分经常被廉价地垃圾收集 老一代:在年轻一代的垃圾收集中幸存下来的对象在这里,这个区域的垃圾收集频率较低,并且使用了对CPU要求更高的进程/算法(我相信它被称为mark sweep) 编辑:如另一位用户所述,PermGen不是名为堆的区域的一部分 PermGen:这个区域充满了你的应用程序类元数据和许多其他不依赖于应用程序使用的东西 所以,知道这一点。。。为

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

java堆的分段如下所示:

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

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

编辑:如另一位用户所述,PermGen不是名为
堆的区域的一部分

  • PermGen:这个区域充满了你的应用程序类元数据和许多其他不依赖于应用程序使用的东西
所以,知道这一点。。。为什么我的PermGen空间在应用程序负载过重时会增长?因为我之前所说的,不管应用程序的负载如何,这个空间不应该逐渐填满,但正如我在开始时所说的,我在一些假设上可能是错的


事实上,如果PermGen空间在增长,有没有垃圾收集或重置它的方法?

你在用类加载器链做一些奇怪的事情?您是在一堆字符串上调用
intern()

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

如果你的烫发基因持续增长,这是一个很难挖掘的领域。通常,当第一次加载新类时,它会增长(反射的某些使用也可能导致这种情况)。插入的字符串也存储在perm gen中

如果您正好在Solaris上,您可以使用jmap-permstat转储perm gen统计数据,但该选项在Windows(以及其他可能的平台)上似乎不可用。这是

从Sun的(您可以查看这些池的大小):

对于热点Java虚拟机,内存 用于串行垃圾收集的池 有以下几点

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

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


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

  • 自定义类加载器,在加载新类后不小心释放旧类
  • 多次重新部署应用程序后仍保留在PermGen中的类(在Dev中比在Prod中更常见)
  • 大量使用代理类,这些类是在运行时综合创建的。当单个类定义可以用于多个实例时,创建新的代理类很容易
这是一个更烦人的调试问题。有很多原因可以让你看到永久使用的增长。这里有两个链接,我发现这两个链接对于理解泄漏是如何发生的以及跟踪导致泄漏的原因都非常有用


如果您使用的是Java EE应用程序,则可能是类加载器泄漏

您可能会发现以下附加链接很有用:


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

  • Java类被加载
  • JAXBContext.newInstance
  • String.intern()

  • 不,该应用程序的主要部分在于反序列化一个大对象图,但该图主要是带有字符串的HashMaps。也许那是在呼叫实习生?不。HashMap不调用intern()。您能否进一步澄清在perm gen增长时发生的情况?你是如何观察到你的烫发基因正在增长的?+1表示非常棒的链接。上周我偶然发现了其中一个,但后来失去了链接。