diff --git a/make/hotspot_version b/make/hotspot_version index cb06ce5571ec140e0fd5d4b677abc30d7ed8e092..75fc4a57deec05d747644b1fbae38d59bfa4b51b 100644 --- a/make/hotspot_version +++ b/make/hotspot_version @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015 HS_MAJOR_VER=25 -HS_MINOR_VER=60 -HS_BUILD_NUMBER=22 +HS_MINOR_VER=66 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/src/os/bsd/vm/jsig.c b/src/os/bsd/vm/jsig.c index a8d98a0846eb64068c3303d7aa2d9ae121d5f960..a3ea0fdd48b4cbaefeed1e8a044723eeba499b6a 100644 --- a/src/os/bsd/vm/jsig.c +++ b/src/os/bsd/vm/jsig.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -36,6 +36,7 @@ #include #include #include +#include #define MAXSIGNUM 32 #define MASK(sig) ((unsigned int)1 << sig) @@ -43,6 +44,9 @@ static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ static unsigned int jvmsigs = 0; /* signals used by jvm */ +static pthread_key_t reentry_flag_key; +static pthread_once_t reentry_key_init_once = PTHREAD_ONCE_INIT; + /* used to synchronize the installation of signal handlers */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; @@ -59,6 +63,15 @@ static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ static bool jvm_signal_installing = false; static bool jvm_signal_installed = false; +#define check_status(cmd) \ + do { \ + int status = (cmd); \ + if (status != 0) { \ + printf("error %s (%d) in " #cmd "\n", strerror(status), status); \ + exit(1); \ + } \ + } while (0) + static void signal_lock() { pthread_mutex_lock(&mutex); /* When the jvm is installing its set of signal handlers, threads @@ -74,8 +87,15 @@ static void signal_unlock() { pthread_mutex_unlock(&mutex); } +static void reentry_tls_init() { + // value for reentry_flag_key will default to NULL (false) + check_status(pthread_key_create(&reentry_flag_key, NULL)); +} + static sa_handler_t call_os_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t res; + if (os_signal == NULL) { if (!is_sigset) { os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); @@ -87,7 +107,12 @@ static sa_handler_t call_os_signal(int sig, sa_handler_t disp, exit(0); } } - return (*os_signal)(sig, disp); + check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); + // set reentry_flag_key to non-NULL to show reentry + check_status(pthread_setspecific(reentry_flag_key, &res)); + res = (*os_signal)(sig, disp); + check_status(pthread_setspecific(reentry_flag_key, NULL)); + return res; } static void save_signal_handler(int sig, sa_handler_t disp) { @@ -161,6 +186,11 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { bool sigused; struct sigaction oldAct; + check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); + if (pthread_getspecific(reentry_flag_key) != NULL) { + return call_os_sigaction(sig, act, oact); + } + signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; diff --git a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 8a3c46c2c3ce78be13254f4ed261f197ffefe257..859a15692cf9709f9700b1b4227dc30f9c2df22d 100644 --- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -189,7 +189,7 @@ public: return CPUVisitor::visit(nodeh, state); } - PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) { + PICL(bool is_fujitsu, bool is_sun4v) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) { if (!open_library()) { return; } @@ -201,7 +201,7 @@ public: if (is_fujitsu) { cpu_class = "core"; } - CPUVisitor cpu_visitor(this, os::processor_count()); + CPUVisitor cpu_visitor(this, (is_sun4v && !is_fujitsu) ? 1 : os::processor_count()); _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper); if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value? _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value(); @@ -494,7 +494,7 @@ int VM_Version::platform_features(int features) { } // Figure out cache line sizes using PICL - PICL picl((features & sparc64_family_m) != 0); + PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); _L2_data_cache_line_size = picl.L2_data_cache_line_size(); return features; diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 917a62f9fb99ba17f6f12cca107e49b40fd20f2a..de5555fb7d58977150a42c00a1a9c8bc8954284d 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -3339,9 +3339,11 @@ void CMSCollector::setup_cms_unloading_and_verification_state() { // Not unloading classes this cycle assert(!should_unload_classes(), "Inconsitency!"); + // If we are not unloading classes then add SO_AllCodeCache to root + // scanning options. + add_root_scanning_option(rso); + if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { - // Include symbols, strings and code cache elements to prevent their resurrection. - add_root_scanning_option(rso); set_verifying(true); } else if (verifying() && !should_verify) { // We were verifying, but some verification flags got disabled. diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index 57091bebeec4fce3907646b1ae1253a45de25668..2f1a2af061e7f917aa85064d868c2ae78d3e4d16 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -439,6 +439,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { if (!constants()->is_shared()) { MetadataFactory::free_metadata(loader_data, constants()); } + // Delete any cached resolution errors for the constant pool + SystemDictionary::delete_resolution_error(constants()); + set_constants(NULL); } diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp index 15916a20eb0e460e601ef83de9d19c999b8284fb..d19b4a1cf1e7accd635c081340fd37d36e808f7c 100644 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -4071,9 +4071,6 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, mnt->adjust_method_entries(the_class(), &trace_name_printed); } - // Fix Resolution Error table also to remove old constant pools - SystemDictionary::delete_resolution_error(old_constants); - if (the_class->oop_map_cache() != NULL) { // Flush references to any obsolete methods from the oop map cache // so that obsolete methods are not pinned. diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index 3d0fc028c8cfc7039cdae9c9ff662909967009cc..8e2c52c9e15d3d0a5a11ad6f152b83b2264bf339 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -3307,6 +3307,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { extern void JDK_Version_init(); + // Preinitialize version info. + VM_Version::early_initialize(); + // Check version if (!is_supported_jni_version(args->version)) return JNI_EVERSION; diff --git a/src/share/vm/runtime/vm_version.hpp b/src/share/vm/runtime/vm_version.hpp index d48b45422829796bbe15b908bffa9b9297e82f81..07ff4ba8d1d2a9beca431588501ab7bc49f7af14 100644 --- a/src/share/vm/runtime/vm_version.hpp +++ b/src/share/vm/runtime/vm_version.hpp @@ -56,6 +56,13 @@ class Abstract_VM_Version: AllStatic { public: static void initialize(); + // This allows for early initialization of VM_Version information + // that may be needed later in the initialization sequence but before + // full VM_Version initialization is possible. It can not depend on any + // other part of the VM being initialized when called. Platforms that + // need to specialize this define VM_Version::early_initialize(). + static void early_initialize() { } + // Name static const char* vm_name(); // Vendor diff --git a/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java b/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java new file mode 100644 index 0000000000000000000000000000000000000000..e4cff831d691792dadc36f3b3c55b9d06bc1f7c7 --- /dev/null +++ b/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014, 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 + * @bug 8076110 + * @summary Redefine running methods that have cached resolution errors + * @library /testlibrary + * @modules java.instrument + * java.base/jdk.internal.org.objectweb.asm + * @build RedefineClassHelper + * @run main RedefineClassHelper + * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors + */ + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +import java.lang.reflect.InvocationTargetException; + +public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes { + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals("C")) { + byte[] b = loadC(false); + return defineClass(name, b, 0, b.length); + } else { + return super.findClass(name); + } + } + + private static byte[] loadC(boolean redefine) { + ClassWriter cw = new ClassWriter(0); + + cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null); + { + MethodVisitor mv; + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null); + mv.visitCode(); + + // First time we run we will: + // 1) Cache resolution errors + // 2) Redefine the class / method + // 3) Try to read the resolution errors that were cached + // + // The redefined method will never run, throw error to be sure + if (redefine) { + createThrowRuntimeExceptionCode(mv, "The redefined method was called"); + } else { + createMethodBody(mv); + } + mv.visitMaxs(3, 0); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + private static void createMethodBody(MethodVisitor mv) { + Label classExists = new Label(); + + // Cache resolution errors + createLoadNonExistentClassCode(mv, classExists); + + // Redefine our own class and method + mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V"); + + // Provoke the same error again to make sure the resolution error cache works + createLoadNonExistentClassCode(mv, classExists); + + // Test passed + mv.visitInsn(RETURN); + + mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]); + mv.visitLabel(classExists); + + createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")"); + } + + private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) { + Label tryLoadBegin = new Label(); + Label tryLoadEnd = new Label(); + Label catchLoadBlock = new Label(); + mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError"); + + // Try to load a class that does not exist to provoke resolution errors + mv.visitLabel(tryLoadBegin); + mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V"); + mv.visitLabel(tryLoadEnd); + + // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen + mv.visitJumpInsn(GOTO, classExists); + + mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" }); + mv.visitLabel(catchLoadBlock); + + // Ignore the expected NoClassDefFoundError + mv.visitInsn(POP); + } + + private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) { + mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); + mv.visitInsn(DUP); + mv.visitLdcInsn(msg); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "", "(Ljava/lang/String;)V"); + mv.visitInsn(ATHROW); + } + + private static Class c; + + public static void redefine() throws Exception { + RedefineClassHelper.redefineClass(c, loadC(true)); + } + + public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors()); + c.getMethod("m").invoke(null); + } +}