HeapDumpOnOutOfMemoryError only works once on periodic tasks

I have several applications that run at regular intervals. To track OutOfMemoryError, I decided to turn on HeapDumpOnOutOfMemoryError, and before that I decided to do some research. In some applications, the maximum heap size is 2 GB, so generating multiple heap heaps in quick succession can eat up all of the disk space.

I wrote a small script to check how it will work.

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) { } } } } 

And here is the result

 $ 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 

It works as I would like, but I would like to know why.

Looking at openjdk6 source code, I found the following

 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(); } } } 

How does the first if statement work?

EDIT: It seems that heapdump should be created every time a message is displayed, but this does not happen. Why is this so?

+4
source share
1 answer

The if statement contains an atomic comparison and exchange operation, which will return 0 if and only if the exchange was performed by the current thread. Compare-and-exchange (also known as compare-and-swap) works as follows:

  • Put the value that you think the variable contains (0 in your case, out_of_memory_reported variable)
  • Enter the value for which you want to exchange the value (1 in your case)
  • If you specify a value, it is replaced with the Atomical value being replaced (no other thread can change the value after it has been compared with your assessment) and returns 0
  • Otherwise, nothing happens and a value other than 0 is returned to indicate an error
+2
source

All Articles