We can use the Java command line option -XX:OnOutOfMemoryError to pass a command to execute when OutOfMemoryError gets thrown.
We will use the same code we have been using in other exercises, which is
class TestEpsilonGC {
static final int ALLOCATION_SIZE = 1024 * 1024; // 1MB
static final int LOOP_COUNT = 12;
static long start;
public static void main(String[] args) {
start();
for (int i = 0; i < LOOP_COUNT; i++) {
System.out.print("Allocating iteration: "+i);
byte[] array = new byte[ALLOCATION_SIZE];
System.out.println(" Done");
}
end();
}
static void start() {
start = System.currentTimeMillis();
}
static void end() {
System.out.println("Time taken: "+(System.currentTimeMillis() - start)+"ms");
}
}
Now create a script file with the command to execute with all the options set. I am running this on my Windows desktop. So using the below command included in a run.bat file
java -verbose:gc -Xmx10M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError="run.bat" TestEpsilonGC
Here we are using run.bat to execute the code, configuring the same script to be executed when OutOfMemoryError is thrown.
Executing this bat file, gets into an infinite loop of executing the same program again and again. You will have to use Ctrl+C to exit from execution. Sample output from running this program is
>java -verbose:gc -Xmx10M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError="run.bat" TestEpsilonGC
[0.008s][info][gc] Using Epsilon
[0.120s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups
[0.164s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 524K (5.12%) used
Allocating iteration: 0[0.180s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 1935K (18.90%) used
Done
Allocating iteration: 1[0.181s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 2959K (28.90%) used
Done
Allocating iteration: 2[0.181s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 3983K (38.90%) used
Done
Allocating iteration: 3[0.183s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 5007K (48.90%) used
Done
Allocating iteration: 4[0.183s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 6031K (58.90%) used
Done
Allocating iteration: 5[0.183s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 7055K (68.90%) used
Done
Allocating iteration: 6[0.183s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 8079K (78.90%) used
Done
Allocating iteration: 7[0.184s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 9103K (88.90%) used
Done
Allocating iteration: 8[0.184s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 10127K (98.90%) used
Done
Allocating iteration: 9java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid22060.hprof ...
Heap dump file created [12675933 bytes in 0.012 secs]
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="run.bat"
# Executing "run.bat"...
D:\Ashok\Work\Java\gc>java -verbose:gc -Xmx10M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError="run.bat" TestEpsilonGC
[0.005s][info][gc] Using Epsilon
[0.005s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups
[0.025s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 524K (5.12%) used
Allocating iteration: 0[0.041s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 1935K (18.90%) used
Done
Allocating iteration: 1[0.042s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 2959K (28.90%) used
Done
Allocating iteration: 2[0.042s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 3983K (38.90%) used
Done
Allocating iteration: 3[0.042s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 5007K (48.90%) used
Done
Allocating iteration: 4[0.043s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 6031K (58.90%) used
Done
Allocating iteration: 5[0.043s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 7055K (68.90%) used
Done
Allocating iteration: 6[0.043s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 8079K (78.90%) used
Done
Allocating iteration: 7[0.044s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 9103K (88.90%) used
Done
Allocating iteration: 8[0.044s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 10127K (98.90%) used
Done
Allocating iteration: 9java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid14840.hprof ...
Heap dump file created [12675933 bytes in 0.011 secs]
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="run.bat"
# Executing "run.bat"...
D:\Ashok\Work\Java\gc>java -verbose:gc -Xmx10M -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError="run.bat" TestEpsilonGC
[0.005s][info][gc] Using Epsilon
[0.005s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups
[0.025s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 524K (5.12%) used
Allocating iteration: 0[0.042s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 1935K (18.90%) used
Done
Allocating iteration: 1[0.042s][info ][gc ] Heap: 10240K reserved, 10240K (100.00%) committed, 2959K (28.90%) used
Done
As you can see, run.bat gets executed each time the OutOfMemoryError is thrown, effectively restarting it whenever it runs out of memory.
Sample code used in this post can be downloaded from https://github.com/ashokkumarta/awesomely-java/tree/main/2021/02/Garbage-Collection/EpsilonGC/Self-restart
No comments:
Post a Comment