代码之家  ›  专栏  ›  技术社区  ›  Pablo Fernandez

为什么永磁空间在增长?

  •  17
  • Pablo Fernandez  · 技术社区  · 14 年前

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

    Java堆是这样分割的:

    • 年轻一代:被创建的对象会出现在这里,这部分被频繁而廉价的垃圾收集。

    • 老一代:在年轻一代的垃圾收集中幸存下来的对象会出现在这里,这一区域的垃圾收集频率较低,并且使用更需要CPU的进程/算法(我认为这称为标记扫描)。

    编辑:如其他用户所述,permgen不是名为 heap

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

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

    实际上,如果permgen空间正在增长,有没有垃圾收集或重置的方法?

    7 回复  |  直到 11 年前
        1
  •  19
  •   Joshua McKinnon    14 年前

    实际上,在Sun的JVM永久代(PermGen)中,它与堆完全分离。你确定你没有看到终身的那一代吗?如果你的永久一代继续成长,这将是值得怀疑的。

    如果你的烫发一直在增长,这是一个很难挖掘的领域。一般来说,当第一次加载新类时,它应该会增长(反射的某些使用也可能导致这种情况)。内部字符串也存储在perm gen中。

    如果您正好在Solaris上,可以使用 JMAP -珀姆斯塔特 转储perm gen统计信息,但该选项在Windows(以及可能的其他平台)上似乎不可用。这里是 the documentation on jmap for Java 6

    来自太阳 guide on JConsole (这将允许您查看这些池的大小):

    对于热点JavaVM,内存 串行垃圾收集池 如下所示。

    • 伊甸园空间(堆):最初从中分配内存的池 对于大多数对象。
    • 幸存者空间(堆):包含存活对象的池 伊甸园的垃圾收集 空间。
    • 持续生成(堆):包含已存在对象的池 在幸存者空间呆了一段时间。
    • 永久生成(非堆):包含所有反射的 虚拟机本身的数据, 例如类和方法对象。用 使用类数据共享的Java VMS, 这一代被划分为 只读和读写区域。
    • 代码缓存(非堆):热点Java VM还包括代码缓存, 包含用于 本机的编译和存储 代码。
        2
  •  6
  •   John Stauffer    14 年前

    我见过最常见的原因是:

    • 自定义类加载器,它在加载新类后不小心释放旧类。
    • 在多次重新部署应用程序后,PermGen中剩余的类(在dev中比prod中更常见)
    • 大量使用代理类,这些类是在运行时合成创建的。当一个类定义可以被多个实例重用时,很容易创建新的代理类。
        3
  •  6
  •   Sydney    12 年前

    这是要调试的更麻烦的问题之一。有很多原因,你可能会看到越来越多的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

        4
  •  2
  •   Jonathan Feinberg    14 年前

    你在用Classloader链子做什么奇怪的事情吗?你在打电话吗? intern() 在一堆绳子上?

        5
  •  2
  •   Arjan Tijms UML GURU    11 年前

    如果您正在使用JavaEE应用程序,它可能是类加载器泄漏。

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

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

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

        6
  •  0
  •   stones333    11 年前

    我见过最常见的原因是:

    1. 加载Java类
    2. JAXBContext.newInstance
    3. 字符串.intern()
        7
  •  0
  •   Arjan Tijms UML GURU    11 年前

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

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