有没有人知道为什么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
答案 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将调试器线程显示为垃圾收集器根目录。
奇怪的是,java 5中的调试应用程序没有这个问题。
答案 1 :(得分:0)
permgen泄漏的一种可能性是每个PyInteger实现的Serializable接口存储在静态class_to_type
映射(PyType.java:101)中,这是一个Jython bug。我所知道的5到7之间permgen分配的唯一有趣变化是7中的intern'd字符串的删除以及对直接字节缓冲区内存分配的一些更改,所以相反,图形的时间行为可能由{ Java 5中每次迭代的类型{3}}。