2012-08-14 6 views
10

Czy ktoś wie, dlaczego java 7 nie może pobrać stałego generowania aplikacji, powodując java.lang.OutOfMemoryError: PermGen, podczas gdy java 5 zbiera ciągłe generowanie i uruchamianie aplikacji dobrze?Java 7 nie zbiera stałego generowania, które jest gromadzone przez java 5

Aplikacja wykonuje ocenę wyrażeń jython w pętli, jedna iteracja jest ok. 5 sekund. ciało pętli wygląda następująco:

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

Zrzuty ekranu z jvisual VM prawdopodobnie przeznaczony aplikacja działa w Java 7 i Java 5.

W obu przypadkach stosowane są te same parametry:

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

java 7 java 5

+1

Czy sprawdziłeś algorytmy gc logując się w JConsole lub innym narzędziu? – kosa

+1

Mogą istnieć różne ustawienia uruchamiania maszyny JVM. Czy w twojej aplikacji jest coś niezwykłego? jak gorący kod, niestandardowe ładowarki itp.? – Andy

+0

Ludzie z GC zawsze szykują GC, próbując desperacko poprawić wydajność, więc nie jestem zaskoczony, że istnieje taka różnica. Moim zdaniem jest to, że koncentrują się teraz na 700 Mb, a nie na 100 Mb, i pozwalają stałej pamięci rozszerzać, a nie wydatkować wysiłek, aby ją kontrolować. Skupiają się na wysokiej wydajności i utrzymują się w granicach 700 Mb zamiast dobrych liczb dla PermGen. – RalphChapin

Odpowiedz

0

Jedną z możliwości wycieku permen jest interfejs szeregowalny As implementowany przez każdy PyInteger przechowywany w statycznej mapie class_to_type (PyType.java:101), jest to Jython bug. Jedyne interesujące zmiany w alokacji permeny między 5 a 7, o których mi wiadomo, to usunięcie łańcuchowych ciągów w 7 i pewne zmiany w przydzielaniu pamięci bufora bajtowego, więc zamiast tego czasowe zachowanie twojego wykresu może być wyjaśnione przez unloading typów na każdej iteracji w Javie 5.

2

Mając mały przykład do odtworzenia problemu, stwierdziłem, że program uruchomiony w java 7 poza Eclipse nie cierpi z powodu wycieku pamięci w ciągłym generowaniu.

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 pokazał wątek debuggera jako root kosza.

GCRoot

Dziwne jest to, że aplikacja w Javie 5 debugowania nie mają tego problemu.

+0

Debugger trzyma te odniesienia? Cholerny. – MilesHampson