diff --git a/make/defs.make b/make/defs.make index 25c0b168e33c56a154283b0419b04a220207cb20..b5a41239cc096bc44cd18a34a824bf751103e93c 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 4840ead09cc4ea2c79623df752e839ce98a78747..be6e855d95145e7942b92e12067162a725144708 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 65c839736ec33cbe7dd6482f01ebb56312c267fe..f25c39d9e1596a9ffb212c02c033d0570702497f 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 e5736a561a65eccad2056d5fdc00679cd9a66207..2b4e33c66ccdde8850f99eb3bb7f6c5f35eb6f90 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 e2941129aa26a69c06e612b0169a4777655e9405..a0febc5c07b5ab32dd3be96830cc370e2e6ca5f5 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* Universe::_the_empty_int_array = NULL; Array* Universe::_the_empty_short_array = NULL; Array* 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 52334d0dbce56f4ee29e2a52d12336a9bb4e0fc7..db806ef6d30291b3adfb959fa22f1eb8533d5a30 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* the_empty_int_array() { return _the_empty_int_array; } static Array* the_empty_short_array() { return _the_empty_short_array; } static Array* 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 f3f291d2b8111d31b6c04c663d7775e3924da66a..a6a7ab088d6ae011983652a48561df4af6f761a2 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 8cf87a5219d5c4d86aa7f793ae03dec04980e7e8..1e44b80b561f4d86fa254f447fb0ee2bf2d44786 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 07a8a7980ec40d57fd9b97188ce7d2aa46d18b77..aa2db58a10ea9a9d13e97466be1d0a009aff2118 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 e8d9e309cc83f84a5f4fcad0ec9baade2c76363d..1e01b2e7a9de6e7aaa1e2c7ccc4a97c0889eb19b 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 0b5029d66bc746f31c28b074146b10c7ab8038ca..232f3501644b05a113f41464e5488233a2a703df 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 f4b5a5b365c452779d2c398852e5651607824876..9ec3c855d74bd55edce120a95abca2c25248febd 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 0000000000000000000000000000000000000000..7e598345758475ba34cfe28407a4dd545ba90646 --- /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 0000000000000000000000000000000000000000..a3c1ce701dd094309b32f036d76f632d69d30624 --- /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"); + } +}