2012-08-14 18 views
10

¿Alguien sabe por qué java 7 no recoge la generación permanente de la aplicación, lo que da como resultado java.lang.OutOfMemoryError: PermGen, mientras que java 5 recopila la generación permanente y la aplicación se ejecuta ¿bien?Java 7 no recoge la generación permanente que se recopila en java 5

La aplicación hace la evaluación de expresiones jython en el ciclo, una iteración es de aprox. 5 seg. cuerpo del bucle se parece a:

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

Imágenes de jvisual vm tomadas para aplicación en ejecución en Java 7 y Java 5.

En ambos casos se utilizan los mismos parámetros:

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

java 7 java 5

+1

¿Ha comprobado los algoritmos de gc al iniciar sesión en JConsole o alguna otra herramienta? – kosa

+1

Puede haber diferentes configuraciones de inicio de JVM. ¿Hay algo inusual en tu aplicación? como el código de carga en caliente, cargadores de clases personalizadas, etc. – Andy

+0

La gente de GC siempre está retocando el GC, intentando desesperadamente mejorar el rendimiento, así que no me sorprende que haya tanta diferencia. Mi __guess__ es que ahora están enfocados en los 700Mb en lugar de en los 100Mb, y están permitiendo que la memoria permanente se expanda en lugar de gastar el esfuerzo por controlarla. Están enfocados en el alto rendimiento y mantenerse dentro de 700Mb en lugar de buenos números para PermGen. – RalphChapin

Respuesta

0

Una posibilidad para la fuga de permgen es la interfase Serializable ace implementado por cada PyInteger que se almacena en un mapa estático class_to_type (PyType.java:101), este es un Jython bug. Los únicos cambios interesantes a la asignación de permgen entre 5 y 7 que conozco son la eliminación de cadenas internas en 7 y algunos cambios en la asignación de memoria de búfer de byte directo, por lo que el comportamiento temporal de su gráfico podría explicarse por el unloading de tipos en cada iteración en Java 5.

2

Teniendo un pequeño ejemplo para reproducir el problema, he encontrado que el programa que se ejecuta en java 7 fuera de Eclipse no sufre pérdida de memoria en la generación permanente.

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 mostraron un hilo depurador como root recolector de basura.

GCRoot

extraño es que la depuración de aplicaciones en Java 5 no tiene este problema.

+0

¿El depurador mantiene esas referencias? Maldita sea. – MilesHampson