5

指定された間隔で実行されるアプリケーションがいくつかあります。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 を作成する必要があるようですが、発生しません。どうしてこんなことに?

4

1 に答える 1

3

if ステートメントには、交換が実行中のスレッドによって実行された場合にのみ 0 を返す、比較と交換のアトミック操作が含まれています。比較交換 (比較交換とも呼ばれます) は、次のように機能します。

  • 変数に含まれていると思われる値を指定します (この場合、変数は out_of_memory_reported です)。
  • 値を交換したい値を指定してください (あなたの場合は 1)
  • 値が指定したものである場合、それは原子的に置換値と交換され(推定値と比較された後、他のスレッドが値を変更することはありません)、0 が返されます。
  • それ以外の場合は何も起こらず、失敗を示すために 0 以外の値が返されます
于 2012-07-13T11:14:46.820 に答える