aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasaha <none@none>2016-01-15 16:21:59 -0800
committerasaha <none@none>2016-01-15 16:21:59 -0800
commit2de4db6a0fec838d8ff5a72b56ef9050ca078f13 (patch)
treefb1d3de1ca0fb9e99a4bba22efa9d52c3fc18ec3
parent680ddca7d8d5f4140c45aed8195296c4dcb6b549 (diff)
parent70f9e8a793e7d5641dfd0e6903eb89071161c7a8 (diff)
downloadjdk8u_hotspot-2de4db6a0fec838d8ff5a72b56ef9050ca078f13.tar.gz
Merge
-rw-r--r--make/defs.make5
-rw-r--r--src/os/aix/vm/perfMemory_aix.cpp11
-rw-r--r--src/os/bsd/vm/perfMemory_bsd.cpp6
-rw-r--r--src/os/solaris/vm/os_solaris.cpp4
-rw-r--r--src/share/vm/memory/universe.cpp9
-rw-r--r--src/share/vm/memory/universe.hpp6
-rw-r--r--src/share/vm/opto/loopTransform.cpp6
-rw-r--r--src/share/vm/opto/loopnode.cpp5
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.cpp4
-rw-r--r--src/share/vm/runtime/globals.hpp9
-rw-r--r--src/share/vm/utilities/debug.cpp12
-rw-r--r--test/TEST.groups4
-rw-r--r--test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java106
-rw-r--r--test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java63
14 files changed, 230 insertions, 20 deletions
diff --git a/make/defs.make b/make/defs.make
index 25c0b168e..b5a41239c 100644
--- a/make/defs.make
+++ b/make/defs.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2016, 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
@@ -285,7 +285,7 @@ ifneq ($(OSNAME),windows)
# Use uname output for SRCARCH, but deal with platform differences. If ARCH
# is not explicitly listed below, it is treated as x86.
- SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc64 zero,$(ARCH)))
+ SRCARCH ?= $(ARCH/$(filter sparc sparc64 ia64 amd64 x86_64 ppc ppc64 zero,$(ARCH)))
ARCH/ = x86
ARCH/sparc = sparc
ARCH/sparc64= sparc
@@ -293,6 +293,7 @@ ifneq ($(OSNAME),windows)
ARCH/amd64 = x86
ARCH/x86_64 = x86
ARCH/ppc64 = ppc
+ ARCH/ppc = ppc
ARCH/zero = zero
# BUILDARCH is usually the same as SRCARCH, except for sparcv9
diff --git a/src/os/aix/vm/perfMemory_aix.cpp b/src/os/aix/vm/perfMemory_aix.cpp
index 4840ead09..be6e855d9 100644
--- a/src/os/aix/vm/perfMemory_aix.cpp
+++ b/src/os/aix/vm/perfMemory_aix.cpp
@@ -201,6 +201,7 @@ static pid_t filename_to_pid(const char* filename) {
// the backing store files. Returns true if the directory is considered
// a secure location. Returns false if the statbuf is a symbolic link or
// if an error occurred.
+//
static bool is_statbuf_secure(struct stat *statp) {
if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
// The path represents a link or some non-directory file type,
@@ -209,15 +210,18 @@ static bool is_statbuf_secure(struct stat *statp) {
return false;
}
// We have an existing directory, check if the permissions are safe.
+ //
if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// The directory is open for writing and could be subjected
// to a symlink or a hard link attack. Declare it insecure.
+ //
return false;
}
- // See if the uid of the directory matches the effective uid of the process.
- //
- if (statp->st_uid != geteuid()) {
+ // If user is not root then see if the uid of the directory matches the effective uid of the process.
+ uid_t euid = geteuid();
+ if ((euid != 0) && (statp->st_uid != euid)) {
// The directory was not created by this user, declare it insecure.
+ //
return false;
}
return true;
@@ -228,6 +232,7 @@ static bool is_statbuf_secure(struct stat *statp) {
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
+//
static bool is_directory_secure(const char* path) {
struct stat statbuf;
int result = 0;
diff --git a/src/os/bsd/vm/perfMemory_bsd.cpp b/src/os/bsd/vm/perfMemory_bsd.cpp
index 65c839736..f25c39d9e 100644
--- a/src/os/bsd/vm/perfMemory_bsd.cpp
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -217,9 +217,9 @@ static bool is_statbuf_secure(struct stat *statp) {
//
return false;
}
- // See if the uid of the directory matches the effective uid of the process.
- //
- if (statp->st_uid != geteuid()) {
+ // If user is not root then see if the uid of the directory matches the effective uid of the process.
+ uid_t euid = geteuid();
+ if ((euid != 0) && (statp->st_uid != euid)) {
// The directory was not created by this user, declare it insecure.
//
return false;
diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp
index e5736a561..2b4e33c66 100644
--- a/src/os/solaris/vm/os_solaris.cpp
+++ b/src/os/solaris/vm/os_solaris.cpp
@@ -2041,7 +2041,9 @@ void os::print_memory_info(outputStream* st) {
st->print(", physical " UINT64_FORMAT "k", os::physical_memory()>>10);
st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10);
st->cr();
- (void) check_addr0(st);
+ if (VMError::fatal_error_in_progress()) {
+ (void) check_addr0(st);
+ }
}
void os::print_siginfo(outputStream* st, void* siginfo) {
diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp
index e2941129a..a0febc5c0 100644
--- a/src/share/vm/memory/universe.cpp
+++ b/src/share/vm/memory/universe.cpp
@@ -114,6 +114,7 @@ oop Universe::_the_min_jint_string = NULL;
LatestMethodCache* Universe::_finalizer_register_cache = NULL;
LatestMethodCache* Universe::_loader_addClass_cache = NULL;
LatestMethodCache* Universe::_pd_implies_cache = NULL;
+LatestMethodCache* Universe::_throw_illegal_access_error_cache = NULL;
oop Universe::_out_of_memory_error_java_heap = NULL;
oop Universe::_out_of_memory_error_metaspace = NULL;
oop Universe::_out_of_memory_error_class_metaspace = NULL;
@@ -129,7 +130,6 @@ oop Universe::_virtual_machine_error_instance = NULL;
oop Universe::_vm_exception = NULL;
oop Universe::_allocation_context_notification_obj = NULL;
-Method* Universe::_throw_illegal_access_error = NULL;
Array<int>* Universe::_the_empty_int_array = NULL;
Array<u2>* Universe::_the_empty_short_array = NULL;
Array<Klass*>* Universe::_the_empty_klass_array = NULL;
@@ -235,6 +235,7 @@ void Universe::serialize(SerializeClosure* f, bool do_all) {
_finalizer_register_cache->serialize(f);
_loader_addClass_cache->serialize(f);
_pd_implies_cache->serialize(f);
+ _throw_illegal_access_error_cache->serialize(f);
}
void Universe::check_alignment(uintx size, uintx alignment, const char* name) {
@@ -663,6 +664,7 @@ jint universe_init() {
Universe::_finalizer_register_cache = new LatestMethodCache();
Universe::_loader_addClass_cache = new LatestMethodCache();
Universe::_pd_implies_cache = new LatestMethodCache();
+ Universe::_throw_illegal_access_error_cache = new LatestMethodCache();
if (UseSharedSpaces) {
// Read the data structures supporting the shared spaces (shared
@@ -1135,7 +1137,8 @@ bool universe_post_init() {
tty->print_cr("Unable to link/verify Unsafe.throwIllegalAccessError method");
return false; // initialization failed (cannot throw exception yet)
}
- Universe::_throw_illegal_access_error = m;
+ Universe::_throw_illegal_access_error_cache->init(
+ SystemDictionary::misc_Unsafe_klass(), m);
// Setup method for registering loaded classes in class loader vector
InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
@@ -1161,7 +1164,7 @@ bool universe_post_init() {
return false; // initialization failed
}
Universe::_pd_implies_cache->init(
- SystemDictionary::ProtectionDomain_klass(), m);;
+ SystemDictionary::ProtectionDomain_klass(), m);
}
// The folowing is initializing converter functions for serialization in
diff --git a/src/share/vm/memory/universe.hpp b/src/share/vm/memory/universe.hpp
index 52334d0db..db806ef6d 100644
--- a/src/share/vm/memory/universe.hpp
+++ b/src/share/vm/memory/universe.hpp
@@ -148,8 +148,7 @@ class Universe: AllStatic {
static LatestMethodCache* _finalizer_register_cache; // static method for registering finalizable objects
static LatestMethodCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector
static LatestMethodCache* _pd_implies_cache; // method for checking protection domain attributes
-
- static Method* _throw_illegal_access_error;
+ static LatestMethodCache* _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError() method
// preallocated error objects (no backtrace)
static oop _out_of_memory_error_java_heap;
@@ -305,6 +304,7 @@ class Universe: AllStatic {
static Method* loader_addClass_method() { return _loader_addClass_cache->get_method(); }
static Method* protection_domain_implies_method() { return _pd_implies_cache->get_method(); }
+ static Method* throw_illegal_access_error() { return _throw_illegal_access_error_cache->get_method(); }
static oop null_ptr_exception_instance() { return _null_ptr_exception_instance; }
static oop arithmetic_exception_instance() { return _arithmetic_exception_instance; }
@@ -314,8 +314,6 @@ class Universe: AllStatic {
static inline oop allocation_context_notification_obj();
static inline void set_allocation_context_notification_obj(oop obj);
- static Method* throw_illegal_access_error() { return _throw_illegal_access_error; }
-
static Array<int>* the_empty_int_array() { return _the_empty_int_array; }
static Array<u2>* the_empty_short_array() { return _the_empty_short_array; }
static Array<Method*>* the_empty_method_array() { return _the_empty_method_array; }
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index f3f291d2b..a6a7ab088 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -1739,6 +1739,12 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale,
}
return true;
}
+ if (is_scaled_iv(exp->in(2), iv, p_scale)) {
+ if (p_offset != NULL) {
+ *p_offset = exp->in(1);
+ }
+ return true;
+ }
if (exp->in(2)->is_Con()) {
Node* offset2 = NULL;
if (depth < 2 &&
diff --git a/src/share/vm/opto/loopnode.cpp b/src/share/vm/opto/loopnode.cpp
index 8cf87a521..1e44b80b5 100644
--- a/src/share/vm/opto/loopnode.cpp
+++ b/src/share/vm/opto/loopnode.cpp
@@ -2328,6 +2328,11 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
#endif
if (skip_loop_opts) {
+ // restore major progress flag
+ for (int i = 0; i < old_progress; i++) {
+ C->set_major_progress();
+ }
+
// Cleanup any modified bits
_igvn.optimize();
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp
index 07a8a7980..aa2db58a1 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -3378,7 +3378,9 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
// not yet in the vtable, because the vtable setup is in progress.
// This must be done after we adjust the default_methods and
// default_vtable_indices for methods already in the vtable.
+ // If redefining Unsafe, walk all the vtables looking for entries.
if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
+ || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
|| ik->is_subtype_of(_the_class_oop))) {
// ik->vtable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
@@ -3393,7 +3395,9 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
// interface, then we have to call adjust_method_entries() for
// every InstanceKlass that has an itable since there isn't a
// subclass relationship between an interface and an InstanceKlass.
+ // If redefining Unsafe, walk all the itables looking for entries.
if (ik->itable_length() > 0 && (_the_class_oop->is_interface()
+ || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
|| ik->is_subclass_of(_the_class_oop))) {
// ik->itable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
index e8d9e309c..1e01b2e7a 100644
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -1279,6 +1279,13 @@ class CommandLineFlags {
"Decay time (in milliseconds) to re-enable bulk rebiasing of a " \
"type after previous bulk rebias") \
\
+ 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 */ \
\
notproduct(bool, TraceRuntimeCalls, false, \
diff --git a/src/share/vm/utilities/debug.cpp b/src/share/vm/utilities/debug.cpp
index 0b5029d66..232f35016 100644
--- a/src/share/vm/utilities/debug.cpp
+++ b/src/share/vm/utilities/debug.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -302,6 +302,16 @@ void report_java_out_of_memory(const char* message) {
VMError err(message);
err.report_java_out_of_memory();
}
+
+ if (CrashOnOutOfMemoryError) {
+ tty->print_cr("Aborting due to java.lang.OutOfMemoryError: %s", message);
+ fatal(err_msg("OutOfMemory encountered: %s", message));
+ }
+
+ if (ExitOnOutOfMemoryError) {
+ tty->print_cr("Terminating due to java.lang.OutOfMemoryError: %s", message);
+ exit(3);
+ }
}
}
diff --git a/test/TEST.groups b/test/TEST.groups
index f4b5a5b36..9ec3c855d 100644
--- a/test/TEST.groups
+++ b/test/TEST.groups
@@ -96,7 +96,8 @@ needs_jdk = \
runtime/Thread/TestThreadDumpMonitorContention.java \
runtime/XCheckJniJsig/XCheckJSig.java \
serviceability/attach/AttachWithStalePidFile.java \
- serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
+ serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \
+ testlibrary_tests/
# JRE adds further tests to compact3
@@ -251,7 +252,6 @@ compact1_minimal = \
serviceability/ \
compiler/ \
testlibrary/ \
- testlibrary_tests/ \
sanity/ \
runtime/ \
gc/ \
diff --git a/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java b/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
new file mode 100644
index 000000000..7e5983457
--- /dev/null
+++ b/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, 2016, 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 com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.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",
+ "-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");
+ }
+
+ System.out.println("PASSED");
+ }
+}
diff --git a/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java b/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java
new file mode 100644
index 000000000..a3c1ce701
--- /dev/null
+++ b/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2016, 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 com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.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.shouldContain("Terminating due to java.lang.OutOfMemoryError: Requested array size exceeds VM limit");
+ System.out.println("PASSED");
+ }
+}