8138745: Implement ExitOnOutOfMemory and CrashOnOutOfMemory in HotSpot
Reviewed-by: dholmes, sla
Contributed-by: cheleswer.sahu@oracle.com
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Dec 08 20:51:09 2015 -0500
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Dec 09 15:31:25 2015 +0530
@@ -1423,6 +1423,13 @@
range(500, max_intx) \
constraint(BiasedLockingDecayTimeFunc,AfterErgo) \
\
+ product(bool, ExitOnOutOfMemoryError, false, \
+ "JVM exits on the first occurrence of an out-of-memory error") \
+ \
+ product(bool, CrashOnOutOfMemoryError, false, \
+ "JVM aborts, producing an error log and core/mini dump, on the " \
+ "first occurrence of an out-of-memory error") \
+ \
/* tracing */ \
\
develop(bool, StressRewriter, false, \
--- a/hotspot/src/share/vm/utilities/debug.cpp Tue Dec 08 20:51:09 2015 -0500
+++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Dec 09 15:31:25 2015 +0530
@@ -305,6 +305,16 @@
if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
VMError::report_java_out_of_memory(message);
}
+
+ if (CrashOnOutOfMemoryError) {
+ tty->print_cr("Aborting due to java.lang.OutOfMemoryError: %s", message);
+ fatal("OutOfMemory encountered: %s", message);
+ }
+
+ if (ExitOnOutOfMemoryError) {
+ tty->print_cr("Terminating due to java.lang.OutOfMemoryError: %s", message);
+ os::exit(3);
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java Wed Dec 09 15:31:25 2015 +0530
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestCrashOnOutOfMemoryError
+ * @summary Test using -XX:+CrashOnOutOfMemoryError
+ * @library /testlibrary
+ * @build jdk.test.lib.*
+ * @run driver TestCrashOnOutOfMemoryError
+ * @bug 8138745
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+public class TestCrashOnOutOfMemoryError {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1) {
+ // This should guarantee to throw:
+ // java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ try {
+ Object[] oa = new Object[Integer.MAX_VALUE];
+ throw new Error("OOME not triggered");
+ } catch (OutOfMemoryError err) {
+ throw new Error("OOME didn't abort JVM!");
+ }
+ }
+ // else this is the main test
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+CrashOnOutOfMemoryError",
+ "-XX:-CreateCoredumpOnCrash", "-Xmx64m", TestCrashOnOutOfMemoryError.class.getName(),"throwOOME");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ int exitValue = output.getExitValue();
+ if (0 == exitValue) {
+ //expecting a non zero value
+ throw new Error("Expected to get non zero exit value");
+ }
+
+ /* Output should look something like this. The actual text will depend on the OS and its core dump processing.
+ Aborting due to java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ # To suppress the following error report, specify this argument
+ # after -XX: or in .hotspotrc: SuppressErrorAt=/debug.cpp:303
+ #
+ # A fatal error has been detected by the Java Runtime Environment:
+ #
+ # Internal Error (/home/cheleswer/Desktop/jdk9/dev/hotspot/src/share/vm/utilities/debug.cpp:303), pid=6212, tid=6213
+ # fatal error: OutOfMemory encountered: Requested array size exceeds VM limit
+ #
+ # JRE version: OpenJDK Runtime Environment (9.0) (build 1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00)
+ # Java VM: OpenJDK 64-Bit Server VM (1.9.0-internal-debug-cheleswer_2015_10_20_14_32-b00, mixed mode, tiered, compressed oops, serial gc, linux-amd64)
+ # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport %p %s %c %P" (or dumping to
+ /home/cheleswer/Desktop/core.6212)
+ #
+ # An error report file with more information is saved as:
+ # /home/cheleswer/Desktop/hs_err_pid6212.log
+ #
+ # If you would like to submit a bug report, please visit:
+ # http://bugreport.java.com/bugreport/crash.jsp
+ #
+ Current thread is 6213
+ Dumping core ...
+ Aborted (core dumped)
+ */
+ output.shouldContain("Aborting due to java.lang.OutOfMemoryError: Requested array size exceeds VM limit");
+ // extract hs-err file
+ String hs_err_file = output.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
+ if (hs_err_file == null) {
+ throw new Error("Did not find hs-err file in output.\n");
+ }
+
+ /*
+ * Check if hs_err files exist or not
+ */
+ File f = new File(hs_err_file);
+ if (!f.exists()) {
+ throw new Error("hs-err file missing at "+ f.getAbsolutePath() + ".\n");
+ }
+
+ /*
+ * Checking the completness of hs_err file. If last line of hs_err file is "END"
+ * then it proves that file is complete.
+ */
+ try (FileInputStream fis = new FileInputStream(f);
+ BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
+ String line = null;
+ String lastLine = null;
+ while ((line = br.readLine()) != null) {
+ lastLine = line;
+ }
+ if (!lastLine.equals("END.")) {
+ throw new Error("hs-err file incomplete (missing END marker.)");
+ } else {
+ System.out.println("End marker found.");
+ }
+ }
+ System.out.println("PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java Wed Dec 09 15:31:25 2015 +0530
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestExitOnOutOfMemoryError
+ * @summary Test using -XX:ExitOnOutOfMemoryError
+ * @library /testlibrary
+ * @build jdk.test.lib.*
+ * @run driver TestExitOnOutOfMemoryError
+ * @bug 8138745
+ */
+
+import jdk.test.lib.ProcessTools;
+import jdk.test.lib.OutputAnalyzer;
+
+public class TestExitOnOutOfMemoryError {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1) {
+ // This should guarantee to throw:
+ // java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ try {
+ Object[] oa = new Object[Integer.MAX_VALUE];
+ throw new Error("OOME not triggered");
+ } catch (OutOfMemoryError err) {
+ throw new Error("OOME didn't terminate JVM!");
+ }
+ }
+
+ // else this is the main test
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+ExitOnOutOfMemoryError",
+ "-Xmx64m", TestExitOnOutOfMemoryError.class.getName(), "throwOOME");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ /*
+ * Actual output should look like this:
+ * Terminating due to java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ */
+ output.shouldHaveExitValue(3);
+ output.stdoutShouldNotBeEmpty();
+ output.shouldContain("Terminating due to java.lang.OutOfMemoryError: Requested array size exceeds VM limit");
+ System.out.println("PASSED");
+ }
+}