2016-08-27 6 views
1

Ich habe eine Java-8-Anwendung, die in Nachrichten über das Netzwerk nimmt und schreibt auf mehrere Memory Mapped-Dateien Java NIO MappedByteBuffer verwenden. Ich habe einen Leser, der Nachrichten gleichzeitig aus diesen Dateien liest und gelöschte Dateien mit MappedByteBuffer wieder löscht. Alles ist glatt, bis ich geschrieben habe, und über 246 GB Daten und meine Anwendung abstürzt mit dem folgendenJava 8 Anwendung, die den gesamten System-RAM verwendet und dann mit einem SIGBUS abstürzt. Was ist denn hier los?

[thread 139611281577728 also had an error][thread 139611278419712 also had an error][thread 139611282630400 also had an error][thread 139611277367040 also had an error][thread 139611283683072 also had an error][thread 139611279472384 also had an error] 





[thread 139611280525056 also had an error] 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGBUS (0x7) at pc=0x00007f02d10526de, pid=44460, tid=0x00007ef9c9088700 
# 
# JRE version: Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13) 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode linux-amd64) 
# Problematic frame: 
# v ~StubRoutines::jint_disjoint_arraycopy 
# 
# Core dump written. Default location: /home/user/core or core.44460 
# 
# An error report file with more information is saved as: 
# /home/user/hs_err_pid44460.log 

Die hs_err_pid44460.log ist leer und die Core-Dumps core.44460 ist etwa 246 GB groß und voll von den Nachrichten, die ich gelesen bin versuchen zu schreiben.

ich mit einer Max-Heap-Größe von 32 GB leite. Laut JConsole habe ich keinen Free Physical Memory mehr und stürze dann ab. JConsole Screen Capture

Warum habe ich keinen RAM mehr? Vergesse ich, einen Datei-Handle zu schließen/meine MMapped-Dateien nicht korrekt zu schließen?

Antwort

1

Obwohl Ihr Programm tatsächlich in der Verwendung von MappedByteBuffers korrekt sein kann, beachten Sie bitte, dass bei einem hohen Zuteilungstempo Phänomene aufgrund einer vorzeitigen Aufhebung der Zuordnung der Puffer auftreten können, was letztendlich eine Verantwortlichkeit von JVM ist und nur während der Ausführung auftreten sollte Garbage Collection von Puffern. Kurz gesagt, die Freigabe von Puffer wird letztlich gelingen, aber wenn es passieren wird sollte kaum vorhersehbar sein.

Sie könnten jedoch die Freigabe ("Bereinigung") von Arbeitsspeicher erzwingen, der den Puffern mithilfe der JVM-Cleaner-Funktionalität (Klasse sun.misc.Cleaner) zugeordnet ist. Bitte beachten Sie this SO question für einige Richtungen, aber lange Geschichte kurz, sollten Sie einfach Cleaner.clean() auf Wegwerf-Puffer, um so früh wie möglich, rufen Sie die Speicherzuordnung Zahlen zu reduzieren und effektiv Ihren Anwendungsfall zu unterstützen.

+1

Die Lösung bestand darin, den 'Cleaner' zu verwenden, um die Arbeit zu erledigen. Insbesondere das half -> http://Stackoverflow.com/a/19447758/1041963 –

+2

Beachten Sie, dass die Verwendung des Cleaners falsch zu Abstürzen führen kann und eine interne API ist, die von Version zu Version – the8472

+1

@the8472 wechseln kann, Sie haben Recht, speziell für API-Änderungen. Ich werde versuchen, meine Antwort so schnell wie möglich mit einigen Anweisungen für Java9 zu aktualisieren, die anfangen, die Angelegenheit von "intern" zu klären (noch weit verbreitet!) APIs, siehe auch: http://openjdk.java.net/jeps/260 – logtwo

0

Sie werden an der virtuellen Speicherbedarf oder Speicherzuordnung des Prozesses suchen, um herauszufinden, ob direkter Puffer die Täter sein könnte.

Wenn es tatsächlich aufgrund von zugeordneten oder direkten Puffern abstürzt, werden Sie entweder ausgeleert (das Ausführen von Heap-Dumps durch einen Speicheranalysator kann diese identifizieren) oder der GC wird zu selten ausgeführt, um sie freizugeben.

+0

Running GC scheint zu helfen. Obwohl der G1 GC die 'G1 Old Generation'-Sammlung nicht oft genug unterstützt (was der scheint, der zu helfen scheint). –

+0

in diesem Fall könnte die Konfiguration der GC häufiger helfen – the8472

0

Sie könnten auch eine aggressivere Garbage Collection wird helfen.

auch vielleicht gefallen diese Option, um zu versuchen, die in J7 eingeführt wurde: -XX: + UseG1GC -XX: ParallelGCThreads = 4 Diese für 4 Threads zu GC parallel

ermöglicht eine Reihe von guten Es gibt Artikel über mehr Ihre Garbage Collector herer, das ich gefunden nützlich (https://blogs.oracle.com/java-platform-group/entry/g1_from_garbage_collector_to)

this helps Tuning.