Verhalten des Arbeitsspeichers mit J2SDK 1.4.2_x

Hallo zusammen,

ich habe seit längerem eine Applikation, die stabil in produktivem Umfeld läuft. Und zwar mit Java 1.4.2_03.
Seit einem Update auf Java 1.4.2_16 habe ich extreme Unterschiede im Verhalten des Arbeitsspeichers festzustellen.

Da ich permanent den Heap in Logdateien ausgebe, kann ich ja nachvollziehen, wie sich dieser über die längere Laufzeit hinweg verhält.

Der im Taskamanager angezeigte Speicherverbrauch ist bekanntlich durch den NonHeap und nativen Speicher bedingt größer als die Ausgabe des Heap-Speichers in der Logdatei.

Nun muss ich nur leider feststellen, dass eben der Speicherverbrauch im Taskmanager exorbitant ansteigt.
Beispiel:

Java 1.4.2_02:

Heap: Total = 169 MB, Used = 132 MB, Free = 37 MB, Max = 254 MB
TaskManager: 238 MB

Java 1.4.2_16:

Heap: Total = 254 MB, Used = 185 MB, Free = 68 MB, Max = 254 MB
TaskManager: 642 MB (Tendenz steigend)

Beide Applikationen laufen ca seit 5 Tagen und haben keinen unterschiedlichen Quelltext.

Auch mit Java 6 ist ein ähnliches Verhalten festzustellen.
Sind also Jemandem Unterschiede in den VM-Versionen bekannt, die zu solch einem Verhalten führen können?

Ich bin gezwungen aus Gründen eines internationalen Einsatzes eine Java-Version >= 1.4.2_12 einzusetzen.

Danke für Tipps

Moien

JVMs können an sich unendlich viel Speicher verbraten: solange der gc nichts wegräumt wächst der Speicher halt weiter. Wann der gc läuft entscheidet die VM, aber die Kritierien und gc-methoden ändern sich teilweise von Version zu Version.

Man kann aber eingreifen. Die Parameter -Xmx und -Xms (Beispiel: java -Xmx200M -Xms200M -jar deine-Anwendung.jar) beschränken die JVM hart auf eine gewisse Speichergrösse und der gc muss damit klarkommen (kann nicht einfachso einen neuen Block Speicher nehmen). Das wäre die Holzhammer-Methode.

Die andere wäre effektiv mit den Entwicklern zu sprechen. Man kann einiges an Diagnose fahren und könnte wahrscheinlich sehr genau bestimmen wo die Objekte herkommen und wieso der gc sie nicht einsammelt. Aber ohne Quellcode läuft da gar nichts.

cu

Die andere wäre effektiv mit den Entwicklern zu sprechen. Man
kann einiges an Diagnose fahren und könnte wahrscheinlich sehr
genau bestimmen wo die Objekte herkommen und wieso der gc sie
nicht einsammelt. Aber ohne Quellcode läuft da gar nichts.

Eine andere Möglichkeit wäre, den Garbage-Collector manuell zum Einsammeln aufzufordern. Allerdings sollte das eigentlich automatisch passieren, so dass die Erfolgsaussicht hier relativ gering ist. Aber aufgrund des ebenfalls sehr geringen Aufwands das zu probieren, ists vielleicht doch nen Versuch wert.

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Sy…

Hi,

tut mir leid, aber das ist murks. Der Entwickler sollte sich die Mühe machen mit einem Profiler seinen Code zu untersuchen.
Manuelle GC-Aufrufe sind ein absolutes No-Go.

Gruss,
Herb

Hi,

tut mir leid, aber das ist murks. Der Entwickler sollte sich
die Mühe machen mit einem Profiler seinen Code zu untersuchen.
Manuelle GC-Aufrufe sind ein absolutes No-Go.

Der manuelle GC Aufruf bringt ja eh nur was, wenn er aus irgendeinem Grund (Bug in der VM etc) nicht automatisch angestoßen wird.

Einen Profiler brauchst du ja dann, wenn dein Programm noch irgendwelche Referenzen auf ungenutzte Objekte hält und du sehen willst, wo das ist. In so einem Fall nützt aber ein manueller GC Aufruf ohnehin nichts, weil der GC die Objekte ja so oder so nicht wegwirft, weil sie ja noch referenziert sind.

Und es gibt natürlich Gründe und Szenarien, in denen ein manueller GC Aufruf auch abgesehen von dem hier diskutierten Sinn macht oder gar notwendig ist. Ein absolutes „no-go“ ist dies daher keinesfalls, wenngleich es in einer „normalen“ Anwendung nie notwendig sein sollte und auch nie gemacht werden sollte (mit dieser Einschränkung stimme ich dir daher zu).

Guten Morgen,

ich habe den Speicher der Applikation bereits mit den Parametern -Xmx und -Xms auf 256M beschränkt (beide gleich gesetzt).
Dennoch wächst der Speicher im Taskmanager unaufhörlich bis irgendwann Schluss ist.

Habe bereits einen Dump (.hprof) erzeugt und diesen analysiert. Nur sieht man eben darin nur die Heap-Sachen und es deuten keine Einträge auf Fehler hin.

Was in der Applikation allerdings gemacht wird, ist ein zyklisches Neuladen einer Klasse, die der Benutzer in einer anderen Applikation neu kompilieren kann. Dadurch wird nicht der Standard-Classloader verwendet, sondern ein URLClassloader dem jedes Mal eine neue URL übergeben wird. Somit wird erreicht, dass die Klasse nicht aus dem Cache verwendet wird sondern wirklich jedes Mal neu geladen wird.

Dieser Mechanismus funktioniert schon seit Jahren ohne Probleme, aber eben mit Java 1.4.2_03.

Danke für weiter Ideen
Bill