Java 7无法收集Java 5可收集的永久代

10

有人知道为什么Java 7无法收集应用程序的永久代,导致出现java.lang.OutOfMemoryError: PermGen错误,而Java 5可以收集永久代并使应用程序运行良好吗?

应用程序在循环中进行Jython表达式的评估,一次迭代大约需要5秒钟。循环主体如下:

PythonInterpreter py = new PythonInterpreter();
py.set("AI", 1);
((PyInteger)py.eval(expr)).getValue()

在Java 7和Java 5中运行的应用程序的jvisual vm截图。

两种情况下都使用相同的参数:

-Xmx700m 
-XX:MaxPermSize=100m
-XX:+HeapDumpOnOutOfMemoryError
-Xloggc:"C:\Temp\gc.log" -XX:+PrintGCDetails  -XX:-TraceClassUnloading -XX:+PrintClassHistogram 

Java 7 Java 5


1
你是否通过登录JConsole或其他工具来检查垃圾回收算法? - kosa
1
可能会有不同的JVM启动设置。你的应用程序中是否有什么异常之处?例如热加载代码、自定义类加载器等等? - Andy
GC的开发人员一直在调整GC,试图拼命提高性能,所以我并不惊讶会有这样的差异。我的猜测是他们现在专注于700Mb而不是100Mb,并且让永久内存扩展而不是花费精力来控制它。他们专注于高性能和保持在700Mb内,而不是PermGen的好数字。 - RalphChapin
2
你已启用堆转储。堆转储告诉你什么?也许有些东西占用了你的永久代内存,以至于它无法被垃圾回收。 - jtahlborn
1
如果您想分析堆转储文件中Permgen的使用情况,这可能会有所帮助:https://sites.google.com/site/eclipsebiz/The-Unknown-Generation-Perm - MilesHampson
2个回答

2

我发现,当我有一个小的示例来重现这个问题时,Java 7中在Eclipse之外运行的程序不会在永久代中发生内存泄漏。

import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

public class Test01 {

  public static void main(String[] args) throws Exception  {
    PySystemState.initialize();
    long startNanos = System.nanoTime();
    for(int i = 0; i < 450000; i++)    {
        PythonInterpreter pi = new PythonInterpreter();
        long elapsedNanos = System.nanoTime() - startNanos;
        int avgStepInMicros = (int)((elapsedNanos / 1000) / (i+1));
        final String code = String.format(
                "stepNo = %d + 1\n" +
                "if stepNo %% 100 == 0:\n" + 
                "  print 'stepNo: %%d,  elapsedMillis: %%d, avgStepInMicros: %%d' %% (stepNo, %d, %d)", i, elapsedNanos/1000000, avgStepInMicros);
        pi.exec(code);
    }
  }
}

MAT显示调试器线程作为垃圾收集器根节点。

GCRoot

奇怪的是,在Java 5中调试应用程序时没有这个问题。


调试器还保留着那些引用?该死。 - MilesHampson

0

Permgen泄漏的一个可能原因是由于每个存储在静态class_to_type映射中的PyInteger实现了Serializable接口(PyType.java:101),这是Jython 错误。我所知道的5和7之间唯一有趣的Permgen分配变化是在7中删除了intern'd字符串并对直接字节缓冲器内存分配进行了一些更改,因此您图表的时间行为可能是由Java 5中每次迭代卸载类型 引起


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接