Java 7无法收集java 5收集的永久生成

时间:2012-08-14 15:39:59

标签: java garbage-collection jython permgen

有没有人知道为什么java 7无法收集永久性的应用程序,导致java.lang.OutOfMemoryError:PermGen,而java 5收集永久代并且app运行良好?

App在循环中对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

2 个答案:

答案 0 :(得分:2)

有一个小例子来重现这个问题,我发现在Eclipse之外的java 7中运行的程序不会受到永久代的内存泄漏的影响。

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中的调试应用程序没有这个问题。

答案 1 :(得分:0)

permgen泄漏的一种可能性是每个PyInteger实现的Serializable接口存储在静态class_to_type映射(PyType.java:101)中,这是一个Jython bug。我所知道的5到7之间permgen分配的唯一有趣变化是7中的intern'd字符串的删除以及对直接字节缓冲区内存分配的一些更改,所以相反,图形的时间行为可能由{ Java 5中每次迭代的类型{3}}。