GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wachsende Nutzung des residenten Speichers (RSS) von Java Process

Ich bin auf das gleiche Problem gestoßen. Dies ist ein bekanntes Problem mit glibc>=2.10

Das Heilmittel besteht darin, diese Umgebungsvariable export MALLOC_ARENA_MAX=4 zu setzen

IBM-Artikel zum Festlegen von MALLOC_ARENA_MAXhttps://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Google nach MALLOC_ARENA_MAX oder suche danach auf SO, um viele Referenzen zu finden.

Möglicherweise möchten Sie auch andere malloc-Optionen optimieren, um eine geringe Fragmentierung des zugewiesenen Speichers zu optimieren:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

Es ist auch möglich, dass ein nativer Speicherverlust vorliegt. Ein häufiges Problem sind native Speicherlecks, die dadurch verursacht werden, dass ZipInputStream nicht geschlossen wird /GZIPInputStream .

Eine typische Art, wie ein ZipInputStream wird durch einen Aufruf von Class.getResource geöffnet /ClassLoader.getResource und Aufruf von openConnection().getInputStream() auf der java.net.URL Instanz oder durch Aufruf von Class.getResourceAsStream /ClassLoader.getResourceAsStream . Man muss sicherstellen, dass diese Ströme immer geschlossen werden.

Einige häufig verwendete Open-Source-Bibliotheken hatten Fehler, die nicht geschlossene java.util.zip.Inflater durchsickern ließen oder java.util.zip.Deflater Instanzen. Beispielsweise hat die Nimbus Jose JWT-Bibliothek ein entsprechendes Speicherleck in Version 6.5.1 behoben. Java JWT (jjwt) hatte einen ähnlichen Fehler, der in Version 0.10.7 behoben wurde. Das Fehlermuster in diesen 2 Fällen war die Tatsache, dass DeflaterOutputStream.close() aufgerufen wurde und InflaterInputStream.close() rufen Sie nicht Deflater.end() an /Inflater.end() wenn ein Deflater /Inflater Instanz vorgesehen ist. In diesen Fällen reicht es nicht aus, den Code auf geschlossene Streams zu überprüfen. Alle Deflater /Inflater Im Code erstellte Instanzen müssen diese .end() verarbeiten können wird angerufen.

Eine Möglichkeit, nach Zip*Stream-Leaks zu suchen, besteht darin, einen Heap-Dump zu erstellen und nach Instanzen einer beliebigen Klasse mit „zip“, „Inflater“ oder „Deflater“ im Namen zu suchen. Dies ist in vielen Heap-Dump-Analysetools wie Yourkit Java Profiler, JProfiler oder Eclipse MAT möglich. Es lohnt sich auch, Objekte im Finalisierungszustand zu überprüfen, da in einigen Fällen der Speicher erst nach der Finalisierung freigegeben wird. Es ist hilfreich, nach Klassen zu suchen, die möglicherweise native Bibliotheken verwenden. Dies gilt auch für TLS/SSL-Bibliotheken.

Es gibt ein OSS-Tool namens Leakchecker von Elastic, das ein Java-Agent ist, der verwendet werden kann, um die Quellen von java.util.zip.Inflater zu finden Instanzen, die nicht geschlossen wurden (.end() nicht aufgerufen).

Bei systemeigenen Speicherlecks im Allgemeinen (nicht nur bei Zip-Bibliothekslecks) können Sie jemalloc verwenden, um systemeigene Speicherlecks zu debuggen, indem Sie malloc-Sampling-Profiling aktivieren, indem Sie die Einstellungen in MALLOC_CONF angeben Umgebungsvariable. Detaillierte Anweisungen finden Sie in diesem Blogbeitrag:http://www.evanjones.ca/java-native-leak-bug.html . Dieser Blogbeitrag enthält auch Informationen zur Verwendung von jemalloc zum Debuggen eines nativen Speicherlecks in Java-Anwendungen. Es gibt auch einen Blogbeitrag von Elastic mit jemalloc und der Erwähnung von Leakchecker, dem Tool, das Elastic als Open Source zur Verfügung gestellt hat, um Probleme aufzuspüren, die durch nicht geschlossene Zip-Inflater-Ressourcen verursacht werden.

Es gibt auch einen Blogbeitrag über ein natives Speicherleck im Zusammenhang mit ByteBuffers. Java 8u102 hat eine spezielle Systemeigenschaft jdk.nio.maxCachedBufferSize um das in diesem Blogbeitrag beschriebene Cache-Problem einzuschränken.

-Djdk.nio.maxCachedBufferSize=262144

Es ist auch gut, immer offene Dateihandles zu überprüfen, um zu sehen, ob das Speicherleck durch eine große Menge von mmap:ed-Dateien verursacht wird. Unter Linux lsof kann verwendet werden, um offene Dateien und offene Sockets aufzulisten:

lsof -Pan -p PID

Der Bericht über die Speicherzuordnung des Prozesses könnte auch dabei helfen, native Speicherlecks zu untersuchen

pmap -x PID

Für Java-Prozesse, die in Docker laufen, sollte es möglich sein, den Befehl lsof oder pmap auf dem "host" auszuführen. Sie können die PID des containerisierten Prozesses mit diesem Befehl finden

docker inspect --format '{{.State.Pid}}' container_id

Es ist auch nützlich, einen Thread-Dump zu erhalten (oder jconsole/JMX zu verwenden), um die Anzahl der Threads zu überprüfen, da jeder Thread 1 MB nativen Speicher für seinen Stack verbraucht. Eine große Anzahl von Threads würde viel Speicher verbrauchen.

Es gibt auch Native Memory Tracking (NMT) in der JVM. Das könnte nützlich sein, um zu überprüfen, ob es die JVM selbst ist, die den nativen Speicher verbraucht.

Das Jattach-Tool kann auch in Container-Umgebungen (Docker) verwendet werden, um Threaddumps oder Heapdumps vom Host auszulösen. Es ist auch in der Lage, jcmd-Befehle auszuführen, die zur Steuerung von NMT benötigt werden.


Linux
  1. Wenn sich ein Prozess verzweigt, wird sein virtueller oder residenter Speicher kopiert?

  2. Hohe Speicherauslastung, aber kein Prozess verwendet sie

  3. Maximale Speicherauslastung eines Prozesses

  4. Grafische Darstellung der Prozessspeichernutzung unter Linux

  5. Ubuntu Linux:Auslagerungsspeicher und Speichernutzung verarbeiten

Linux – Speichernutzung für einen einzelnen Linux-Prozess begrenzen?

Tool, das die Protokollierung der Speichernutzung ermöglicht?

Maximale Speicherauslastung eines Linux/Unix-Prozesses

CPU-Auslastung und Speicherauslastung eines einzelnen Prozesses unter Linux abrufen?

Speichernutzung des aktuellen Prozesses in C

Korrekte Bestimmung der Speichernutzung in Linux