Java Memory Leak oder normal?

Janisplayer

Cadet 1st Year
Registriert
Juli 2019
Beiträge
10
Hallo zusammen, ich hätte mal eine Frage an die Java Entwickler.
Momentan bringt mich ein MC Server (Paper 30 Plugins) auf Java (x86 64 Bit) zum durchdrehen.
Ich habe 1000 MB zugewisen, aber der Java Prozess nutzt laut htop einfach 300 bis 400 MB mehr.
So viel RAM zum übersetzen kann ja wohl kaum notwendig sein.
Ich habe jetzt schon extra den RAM auf 1400 und eine Auslagerungsdatei erstellt, damit Ubuntu nicht immer meinen Server killt.
Ich habe auch schon den Heap ausgelesen und nichts gefunden, was so viel braucht, eher im Gegenteil es wird nicht so viel genutzt.
Dieses Problem tritt immer auf, wenn Chunks geladen werden, also Speicher reserviert wird.
Ich bin jedenfalls verwundert.
Da ihr wahrscheinlich als Java Entwickler euch besser mit der Laufzeitung auskennt, hoffe ich ihr könnt mir eine Antwort geben.
Ich kenne mich nur ein wenig mit asm, c , c++, Javascript, Python aus und habe mit solchen Laufzeit Problemen eher weniger zu tun.
 
  • Gefällt mir
Reaktionen: Janisplayer
Java braucht temporär immer einen Haufen Speicher, weil Speicher periodisch durch den Garbage Collector freigegeben wird. D.h. wenn du z.B. 1000 Objekte kopierst und die Referenzen der 1000 Originale löschst, dann hast du erst mal 2000 Objekte im Speicher, bis der Garbage Collector seine Runden dreht.
In Sprachen ohne Garbage Collector löscht man die nicht mehr referenzierten Objekte sofort aus dem Speicher, d.h. dort tritt dieser Overhead nicht auf.

Die Speicherverwaltung der JVM ist zudem recht komplex. Womit hast du denn 1000MB zugewiesen? Die JVM selbst braucht ca. 150MB. Dazu kommen dann die geladenen Klassen des Programms. Und dann noch der Heap Space.

Du könntest auch versuchen einen anderen Garbage Collector oder eine andere JVM zu verwenden. Die verhalten sich da alle etwas unterschiedlich, wie wann wo und wie viel Speicher wie schnell wieder freigegeben wird.

Btw: Laut MineCraft Wiki werden 2-3GB RAM für einen LAN Party Server empfohlen.
 
  • Gefällt mir
Reaktionen: Janisplayer
Hallo,
kurze Korrektur zu diversen Aussagen:

Die Referenzen selbst liegen auf dem Stack @benneq und unterliegen somit nicht dem GC. Der GC bereinigt nur den Heap. Zudem ist der Speicherplatzbedarf bei Referenzen nur gering:

4 Byte pro Referenz bei 32-Bit Systemen * 2000 Referenzen (dein Beispiel) ergeben schlappe 8 KByte.
8 Byte pro Referenz bei 64-Bit Systemen * 2000 Referenzen (dein Beispiel) ergeben gerade 16 KByte.

Und die Aussage, dass der GC einen „haufen“ Speicher benötigt halte ich ebenso für fragwürdig. Der Garbage Collector läuft ja als Dienst in der JVM die ganze Zeit mit. Er kopiert auch keinen Speicher (was temporär auch mehr Speicher benötigen würde), sondern verschiebt diesen nach der Speicherbereinigung nur „nach vorne“.

@Janisplayer:
Es ist tatsächlich möglich eine Art Memleak in Java zu programmieren. Dabei handelt es sich nicht um ein klassisches Memkeak (kein Pointer mehr auf allokierten Speicher), sondern eher um das Blockieren großer, komplexer und nicht mehr benötigter Objekte (z.B. Collections) für den GC.

greetz
hroessler
 
  • Gefällt mir
Reaktionen: Janisplayer
Ein memory leak kannst du in der Regel daran erkennen, dass der Speicherbedarf mit der Zeit steigt und sich nie auf ein Maximum einpendelt.
 
  • Gefällt mir
Reaktionen: Janisplayer
hroessler schrieb:
Die Referenzen selbst liegen auf dem Stack @benneq und unterliegen somit nicht dem GC. Der GC bereinigt nur den Heap. Zudem ist der Speicherplatzbedarf bei Referenzen nur gering
Wenn man zu viel zwischen den Zeilen liest...
Ich sprach von „Kopien von Objekten“. Nicht vom Kopieren einer Referenz.
 
  • Gefällt mir
Reaktionen: hroessler
hroessler schrieb:
Ahh, du meintest tiefes kopieren... 😋
Exakt. Wir leben doch schließlich im Funktionalen Zeitalter wo man alles so immutable wie möglich macht :D
 
  • Gefällt mir
Reaktionen: hroessler
Wo, hätte nicht gedacht, dass ich gleich so viele Antworten bekomme und dann noch so gute.
Danke an euch alle.

Also so weit ich es verstanden habe, ist so ein hoher RAM verbraucht nicht normal.
Das sind denke ich, alle Informationen die ihr braucht. :)
start.sh:
Bash:
screen -AmdS minecraft java -server -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=2 -XX:+AggressiveOpts -Xms1400M -Xmx1400M -jar /home/mcserver/mcserver/paper-137.jar nogui
Timings und alle Plugins:
https://timings.aikar.co/?id=f168259ce0eb4aa5b914427a09700316
JVM Heap:
heap-dump-2019-07-27_12.41.14
Hätte noch mehr von älteren Serverversionen, sehen aber alle gleich unauffällig aus.
Benutze Java-Version und System: schrieb:
OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.16.04.1-b03)
OpenJDK 64-Bit Server VM (build 25.212-b03, mixed mode)

Edit:
Ich habe Multiverse-Core geupdatet auf einmal ist der maximale RAM verbrauch auf 170? MB gefallen.
Ich werde mal die Plugins durchgehen.
Edit2: Das kann nur normal sein, der RAM Verbrauch steigt nach einer Zeit wieder nach oben.
 

Anhänge

  • Memory.png
    Memory.png
    717,9 KB · Aufrufe: 214
  • htop.PNG
    htop.PNG
    43,1 KB · Aufrufe: 214
  • Heapdump Paper 1.PNG
    Heapdump Paper 1.PNG
    69,2 KB · Aufrufe: 206
Zuletzt bearbeitet:
Zurück
Oben