Java-JAR-Speicherauslastung VS-Klassenspeicherauslastung

8

Ich habe kürzlich meine große Java-Anwendung so geändert, dass sie in JARs anstelle von einzelnen Klassendateien geliefert wird. Ich habe 405 JARS, die 5000 Klassendateien enthalten. Mein Problem ist, dass, wenn ich meine Programme als JARs (Klassenpfad ist ein Platzhalter, um alle JARs zu bekommen) laufen Java wird immer mehr Speicher verwenden. Ich habe die Erinnerung gesehen gehen & gt; 2GB und es scheint, als ob Java nicht Stop-the-World-Garbage-Collections macht, um den Speicher niedriger zu halten. Wenn ich genau dasselbe Programm gegen die explodierten JARs (nur Klassendateien) ausführe, bleibt die Java-Speichernutzung viel niedriger (& lt; 256 MB) und bleibt dort. Dies geschieht in Oracle Java 8 unter Windows 7 (x64) und Windows Server (x64). Warum würde das Packen meiner Anwendung als JARs das Speicherprofil ändern? Auch habe ich das Programm für eine lange Zeit als JARs mit dem maximalen Speicher auf 128 MB ohne Probleme laufen lassen, so habe ich kein Speicherleck.

Mit JAR-Dateien im Klassenpfad

Mit Klassendateien im Klassenpfad

Bearbeiten: Ich akzeptierte die Antwort von @K Erlandsson, weil ich denke, dass es die beste Erklärung ist und das ist nur eine hässliche Eigenart von Java. Vielen Dank (und besonders @K Erlandsson) für Ihre Hilfe.

    
Adam 26.06.2015, 17:54
quelle

2 Antworten

3

Als Erstes ist zu beachten, dass die Speicherkapazität, die auf dem Heap vollständig verwendet wird, nicht immer sehr interessant ist, da ein großer Teil des belegten Speichers unbrauchbar ist und vom nächsten GC gelöscht wird.

Wieviel Heap von live Objekten verwendet wird, um die Sie sich kümmern müssen. Sie schreiben in einen Kommentar:

  

Ich weiß nicht, ob das wichtig ist, aber wenn ich jvisualvm.exe verwende, um einen GC zu erzwingen   (Markieren Sie Sweep) die Heap Speicherauslastung wird löschen fast alle löschen   Heapspeicher.

Das ist wichtig. Viel . Das bedeutet, wenn Sie bei der Verwendung Ihrer JAR-Dateien eine höhere Heap-Nutzung sehen, sehen Sie mehr Garbage , nicht mehr von Live-Objekten belegten Speicher. Der Müll wird gelöscht, wenn Sie einen GC machen und alles ist gut.

Beim Laden von Klassen aus JAR-Dateien wird vorübergehend mehr Speicher belegt, als wenn sie aus Klassendateien geladen werden. Die JAR-Dateien müssen geöffnet, gesucht und gelesen werden. Dies erfordert mehr Operationen und mehr temporäre Daten, als einfach eine bestimmte .class -Datei zu öffnen und zu lesen.

Da der Großteil der Heap-Nutzung von einem GC gelöscht wird, ist diese zusätzliche Speicherbelegung nicht besonders wichtig.

Sie schreiben auch:

  

Java wird immer mehr Speicher verwenden. Ich habe die Erinnerung gesehen   gehen & gt; 2GB und es scheint wie Java nicht Stop-the-World-Müll   Sammlungen, um den Speicher niedriger zu halten.

Dies ist ein typisches Verhalten. Der GC läuft nur, wenn die JVM dies für notwendig hält. Die JVM wird dies abhängig vom Speicherverhalten einstellen.

Bearbeiten: Jetzt, da wir Ihre jConsole-Images sehen, sehen wir einen Unterschied im committed Heap-Speicher (250 MB gegenüber 680 MB). Committed Heap ist die tatsächliche Größe des Heapspeichers. Dies variiert (bis zu dem, was Sie mit -Xmx festlegen), je nachdem, was JVM für die beste Leistung Ihrer Anwendung erwartet. Allerdings wird es meist zunehmen, fast nie abnehmen.

Für den JAR-Fall hat die JVM Ihrer Anwendung einen größeren Heap zugewiesen. Wahrscheinlich, weil während des anfänglichen Klassenladens mehr Speicher benötigt wird. Die JVM dachte dann, ein größerer Haufen wäre schneller.

Wenn Sie einen größeren Heap und mehr festgeschriebenen Arbeitsspeicher haben, müssen Sie mehr Arbeitsspeicher verwenden, bevor Sie einen GC ausführen. Aus diesem Grund sehen Sie in beiden Fällen den Unterschied in der Speichernutzung.

Bottom line: All die zusätzliche Verwendung, die Sie sehen, ist Müll, keine Live-Objekte, weshalb Sie sich um dieses Verhalten nicht kümmern müssen, es sei denn, Sie haben ein tatsächliches Problem, da der Speicher wiederhergestellt wird der nächste GC.

    
K Erlandsson 26.06.2015, 20:33
quelle
0

Es ist ziemlich üblich, Ressourcen aus dem Klassenpfad zu laden. Wenn eine Ressource aus einer JAR-Datei stammt, behält das URL-Objekt einen Verweis auf den JAR-Dateieintrag. Dies könnte etwas Speicherverbrauch hinzufügen. Es ist möglich, dieses Zwischenspeichern zu deaktivieren, indem Sie das Standard-URL-Caching deaktivieren.

Die API zum Deaktivieren des standardmäßigen URL-Cachings ist ziemlich umständlich:

%Vor%

Deaktivieren Sie das Standard-URL-Caching beim Start Ihrer Anwendung.

Tomcat deaktiviert das URL-Caching bereits standardmäßig, da es ebenfalls Probleme mit der Dateisperrung verursacht und die Aktualisierung von JAR-Dateien in einer laufenden Anwendung verhindert.

Ссылка

    
Lari Hotari 26.06.2015 21:02
quelle

Tags und Links