指定された間隔で実行されるアプリケーションがいくつかあります。OutOfMemoryError を監視するために、HeapDumpOnOutOfMemoryError を有効にすることにしました。これを行う前に、調査を行うことにしました。一部のアプリケーションでは最大ヒープ サイズが 2GB であるため、複数のヒープ ダンプを立て続けに生成すると、すべてのディスク スペースが消費される可能性があります。
それがどのように機能するかを確認するために、小さなスクリプトを作成しました。
import java.util.LinkedList;
import java.util.List;
public class Test implements Runnable{
public static void main(String[] args) throws Exception {
new Thread(new Test()).start();
}
public void run() {
while (true) {
try{
List<Object> list = new LinkedList<Object>();
while (true){
list.add(new Object());
}
}
catch (Throwable e){
System.out.println(e);
}
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {
}
}
}
}
そして、これが結果です
$ java -XX:+HeapDumpOnOutOfMemoryError -Xmx2M Test
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid25711.hprof ...
Heap dump file created [14694890 bytes in 0,101 secs]
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
それは私が望むように機能しますが、その理由を知りたいです。
openjdk6 ソースコードを見ると、次のことがわかりました
void report_java_out_of_memory(const char* message) {
static jint out_of_memory_reported = 0;
// A number of threads may attempt to report OutOfMemoryError at around the
// same time. To avoid dumping the heap or executing the data collection
// commands multiple times we just do it once when the first threads reports
// the error.
if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
// create heap dump before OnOutOfMemoryError commands are executed
if (HeapDumpOnOutOfMemoryError) {
tty->print_cr("java.lang.OutOfMemoryError: %s", message);
HeapDumper::dump_heap_from_oome();
}
if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
VMError err(message);
err.report_java_out_of_memory();
}
}
}
最初の if ステートメントはどのように機能しますか?
編集: メッセージが出力されるたびに heapdump を作成する必要があるようですが、発生しません。どうしてこんなことに?