# HG changeset patch # User dlong # Date 1426196727 14400 # Node ID 6d817035633c26944ea483fbc06f6185514ddeac # Parent 7619adc72abd91d686a68724f525c3ec3c69e389# Parent d68158e12cea4ae415460ff8d9610285ef2634c4 Merge diff -r 7619adc72abd -r 6d817035633c .hgtags --- a/.hgtags Tue Mar 03 13:06:16 2015 -0800 +++ b/.hgtags Thu Mar 12 17:45:27 2015 -0400 @@ -599,3 +599,5 @@ 0fb1ac49ae7764c5d7c6dfb9fe046d0e1a4eb5aa hs25.60-b04 586a449cd30332dd53c0f74bf2ead6f3d4724bfc jdk8u60-b04 74931e85352be8556eaa511ca0dd7c38fe272ec3 hs25.60-b05 +b13f1890afb8abc31ecb9c21fd2ba95aba3e33f8 jdk8u60-b05 +b17a8a22a0344e3c93e2e4677de20d35f99cf4f5 hs25.60-b06 diff -r 7619adc72abd -r 6d817035633c agent/src/os/solaris/proc/saproc.cpp --- a/agent/src/os/solaris/proc/saproc.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/agent/src/os/solaris/proc/saproc.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -314,7 +314,7 @@ handle = dlopen(name, mode); } if (_libsaproc_debug) { - printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%x\n", name, handle); + printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle); } return handle; } @@ -661,30 +661,30 @@ // read FileMapHeader size_t n = read(fd, pheader, sizeof(struct FileMapHeader)); if (n != sizeof(struct FileMapHeader)) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check file magic if (pheader->_magic != 0xf00baba2) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2", classes_jsa, pheader->_magic); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check version if (pheader->_version != CURRENT_ARCHIVE_VERSION) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d", classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } diff -r 7619adc72abd -r 6d817035633c agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java --- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Tue Mar 03 13:06:16 2015 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Thu Mar 12 17:45:27 2015 -0400 @@ -51,6 +51,9 @@ private static final int C_INT32_SIZE = 4; private static final int C_INT64_SIZE = 8; private static int pointerSize = UNINITIALIZED_SIZE; + // Counter to ensure read loops terminate: + private static final int MAX_DUPLICATE_DEFINITIONS = 100; + private int duplicateDefCount = 0; private static final boolean DEBUG; static { @@ -166,6 +169,10 @@ typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); + if (typeEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Start iterating down it until we find an entry with no name Address typeNameAddr = null; do { @@ -192,7 +199,11 @@ } entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); - } while (typeNameAddr != null); + } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void initializePrimitiveTypes() { @@ -395,6 +406,10 @@ structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); + if (structEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMStructEntry* Address entryAddr = lookupInProcess("gHotSpotVMStructs"); // Dereference this once to get the pointer to the first VMStructEntry @@ -472,6 +487,11 @@ intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); + if (intConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + + // Fetch the address of the VMIntConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); // Dereference this once to get the pointer to the first VMIntConstantEntry @@ -501,12 +521,17 @@ } else { System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions"); + } } private void readVMLongConstants() { @@ -519,6 +544,10 @@ longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); + if (longConstantEntryArrayStride == 0L) { + throw new RuntimeException("zero stride: cannot read types."); + } + // Fetch the address of the VMLongConstantEntry* Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); // Dereference this once to get the pointer to the first VMLongConstantEntry @@ -548,12 +577,17 @@ } else { System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + "had its value declared as " + value + " twice. Continuing."); + duplicateDefCount++; } } } entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); - } while (nameAddr != null); + } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS); + + if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) { + throw new RuntimeException("too many duplicate definitions."); + } } private BasicType lookupOrFail(String typeName) { @@ -740,9 +774,10 @@ } if (!typeNameIsPointerType(typeName)) { - System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + - "had its size declared as " + size + " twice. Continuing."); - } + System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + + "had its size declared as " + size + " twice. Continuing."); + duplicateDefCount++; + } } } diff -r 7619adc72abd -r 6d817035633c make/hotspot_version --- a/make/hotspot_version Tue Mar 03 13:06:16 2015 -0800 +++ b/make/hotspot_version Thu Mar 12 17:45:27 2015 -0400 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=60 -HS_BUILD_NUMBER=05 +HS_BUILD_NUMBER=07 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 7619adc72abd -r 6d817035633c make/linux/makefiles/gcc.make --- a/make/linux/makefiles/gcc.make Tue Mar 03 13:06:16 2015 -0800 +++ b/make/linux/makefiles/gcc.make Thu Mar 12 17:45:27 2015 -0400 @@ -337,47 +337,41 @@ # Note: The Itanium gcc compiler crashes when using -gstabs. DEBUG_CFLAGS/ia64 = -g DEBUG_CFLAGS/amd64 = -g - DEBUG_CFLAGS/arm = -g - DEBUG_CFLAGS/ppc = -g DEBUG_CFLAGS/ppc64 = -g DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) # Clang doesn't understand -gstabs - DEBUG_CFLAGS += -g + DEBUG_CFLAGS/$(BUILDARCH) = -g else - DEBUG_CFLAGS += -gstabs + DEBUG_CFLAGS/$(BUILDARCH) = -gstabs endif endif ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) FASTDEBUG_CFLAGS/ia64 = -g FASTDEBUG_CFLAGS/amd64 = -g - FASTDEBUG_CFLAGS/arm = -g - FASTDEBUG_CFLAGS/ppc = -g FASTDEBUG_CFLAGS/ppc64 = -g - FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) + FASTDEBUG_CFLAGS += $(FASTDEBUG_CFLAGS/$(BUILDARCH)) ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) # Clang doesn't understand -gstabs - FASTDEBUG_CFLAGS += -g + FASTDEBUG_CFLAGS/$(BUILDARCH) = -g else - FASTDEBUG_CFLAGS += -gstabs + FASTDEBUG_CFLAGS/$(BUILDARCH) = -gstabs endif endif OPT_CFLAGS/ia64 = -g OPT_CFLAGS/amd64 = -g - OPT_CFLAGS/arm = -g - OPT_CFLAGS/ppc = -g OPT_CFLAGS/ppc64 = -g OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) ifeq ($(USE_CLANG), true) # Clang doesn't understand -gstabs - OPT_CFLAGS += -g + OPT_CFLAGS/$(BUILDARCH) = -g else - OPT_CFLAGS += -gstabs + OPT_CFLAGS/$(BUILDARCH) = -gstabs endif endif endif diff -r 7619adc72abd -r 6d817035633c src/os/solaris/vm/jvm_solaris.h --- a/src/os/solaris/vm/jvm_solaris.h Tue Mar 03 13:06:16 2015 -0800 +++ b/src/os/solaris/vm/jvm_solaris.h Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -41,7 +41,9 @@ * JNI conversion, which should be sorted out later. */ +#define __USE_LEGACY_PROTOTYPES__ #include /* For DIR */ +#undef __USE_LEGACY_PROTOTYPES__ #include /* For MAXPATHLEN */ #include /* For socklen_t */ #include /* For F_OK, R_OK, W_OK */ diff -r 7619adc72abd -r 6d817035633c src/share/vm/ci/bcEscapeAnalyzer.cpp --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -42,7 +42,7 @@ #define TRACE_BCEA(level, code) #endif -// Maintain a map of which aguments a local variable or +// Maintain a map of which arguments a local variable or // stack slot may contain. In addition to tracking // arguments, it tracks two special values, "allocated" // which represents any object allocated in the current @@ -318,14 +318,16 @@ bool must_record_dependencies = false; for (i = arg_size - 1; i >= 0; i--) { ArgumentMap arg = state.raw_pop(); - if (!is_argument(arg)) + // Check if callee arg is a caller arg or an allocated object + bool allocated = arg.contains_allocated(); + if (!(is_argument(arg) || allocated)) continue; for (int j = 0; j < _arg_size; j++) { if (arg.contains(j)) { _arg_modified[j] |= analyzer._arg_modified[i]; } } - if (!is_arg_stack(arg)) { + if (!(is_arg_stack(arg) || allocated)) { // arguments have already been recognized as escaping } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { set_method_escape(arg); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -6634,7 +6634,6 @@ } void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) { - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer_cm->gc_id()); TraceCollectorStats tcs(counters()); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -1297,7 +1297,6 @@ // Timing assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant"); - gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); { diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/g1/vm_operations_g1.cpp --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -230,7 +230,6 @@ } void VM_CGC_Operation::doit() { - gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm(), G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id()); SharedHeap* sh = SharedHeap::heap(); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -167,7 +167,6 @@ { HandleMark hm; - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer->gc_id()); TraceCollectorStats tcs(counters()); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -2054,7 +2054,6 @@ gc_task_manager()->task_idle_workers(); heap->set_par_threads(gc_task_manager()->active_workers()); - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id()); TraceCollectorStats tcs(counters()); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -329,7 +329,6 @@ ResourceMark rm; HandleMark hm; - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id()); TraceCollectorStats tcs(counters()); diff -r 7619adc72abd -r 6d817035633c src/share/vm/gc_implementation/shared/gcTraceTime.cpp --- a/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -49,10 +49,8 @@ } if (_doit) { - if (PrintGCTimeStamps) { - gclog_or_tty->stamp(); - gclog_or_tty->print(": "); - } + gclog_or_tty->date_stamp(PrintGCDateStamps); + gclog_or_tty->stamp(PrintGCTimeStamps); if (PrintGCID) { gclog_or_tty->print("#%u: ", gc_id.id()); } diff -r 7619adc72abd -r 6d817035633c src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/memory/genCollectedHeap.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -384,7 +384,6 @@ bool complete = full && (max_level == (n_gens()-1)); const char* gc_cause_prefix = complete ? "Full GC" : "GC"; - gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later // so we can assume here that the next GC id is what we want. diff -r 7619adc72abd -r 6d817035633c src/share/vm/memory/guardedMemory.hpp --- a/src/share/vm/memory/guardedMemory.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/memory/guardedMemory.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -235,7 +235,7 @@ * @return the size of the user data. */ size_t get_user_size() const { - assert(_base_addr, "Not wrapping any memory"); + assert(_base_addr != NULL, "Not wrapping any memory"); return get_head_guard()->get_user_size(); } @@ -245,7 +245,7 @@ * @return the user data pointer. */ u_char* get_user_ptr() const { - assert(_base_addr, "Not wrapping any memory"); + assert(_base_addr != NULL, "Not wrapping any memory"); return _base_addr + sizeof(GuardHeader); } @@ -281,7 +281,7 @@ memset(get_user_ptr(), ch, get_user_size()); } -public: + public: /** * Return the total size required for wrapping the given user size. * diff -r 7619adc72abd -r 6d817035633c src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/prims/jniCheck.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, 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 @@ -53,6 +53,8 @@ # include "jniTypes_ppc.hpp" #endif +// Complain every extra number of unplanned local refs +#define CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD 32 // Heap objects are allowed to be directly referenced only in VM code, // not in native code. @@ -168,12 +170,42 @@ * SUPPORT FUNCTIONS */ +/** + * Check whether or not a programmer has actually checked for exceptions. According + * to the JNI Specification ("jni/spec/design.html#java_exceptions"): + * + * There are two cases where the programmer needs to check for exceptions without + * being able to first check an error code: + * + * - The JNI functions that invoke a Java method return the result of the Java method. + * The programmer must call ExceptionOccurred() to check for possible exceptions + * that occurred during the execution of the Java method. + * + * - Some of the JNI array access functions do not return an error code, but may + * throw an ArrayIndexOutOfBoundsException or ArrayStoreException. + * + * In all other cases, a non-error return value guarantees that no exceptions have been thrown. + */ +static inline void +check_pending_exception(JavaThread* thr) { + if (thr->has_pending_exception()) { + NativeReportJNIWarning(thr, "JNI call made with exception pending"); + } + if (thr->is_pending_jni_exception_check()) { + IN_VM( + tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s", + thr->get_pending_jni_exception_check()); + thr->print_stack(); + ) + thr->clear_pending_jni_exception_check(); // Just complain once + } +} + + static inline void functionEnterCritical(JavaThread* thr) { - if (thr->has_pending_exception()) { - NativeReportJNIWarning(thr, "JNI call made with exception pending"); - } + check_pending_exception(thr); } static inline void @@ -187,9 +219,7 @@ if (thr->in_critical()) { tty->print_cr("%s", warn_other_function_in_critical); } - if (thr->has_pending_exception()) { - NativeReportJNIWarning(thr, "JNI call made with exception pending"); - } + check_pending_exception(thr); } static inline void @@ -201,9 +231,20 @@ } static inline void -functionExit(JNIEnv *env) +functionExit(JavaThread* thr) { - /* nothing to do at this time */ + JNIHandleBlock* handles = thr->active_handles(); + size_t planned_capacity = handles->get_planned_capacity(); + size_t live_handles = handles->get_number_of_live_handles(); + if (live_handles > planned_capacity) { + IN_VM( + tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu", + live_handles, planned_capacity); + thr->print_stack(); + ) + // Complain just the once, reset to current + warn threshold + handles->set_planned_capacity(live_handles + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); + } } static inline void @@ -508,7 +549,7 @@ jniCheck::validate_object(thr, loader); ) jclass result = UNCHECKED()->DefineClass(env, name, loader, buf, len); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -520,7 +561,7 @@ jniCheck::validate_class_descriptor(thr, name); ) jclass result = UNCHECKED()->FindClass(env, name); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -532,7 +573,7 @@ jniCheck::validate_object(thr, method); ) jmethodID result = UNCHECKED()->FromReflectedMethod(env, method); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -544,7 +585,7 @@ jniCheck::validate_object(thr, field); ) jfieldID result = UNCHECKED()->FromReflectedField(env, field); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -560,7 +601,7 @@ ) jobject result = UNCHECKED()->ToReflectedMethod(env, cls, methodID, isStatic); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -572,7 +613,7 @@ jniCheck::validate_class(thr, sub, true); ) jclass result = UNCHECKED()->GetSuperclass(env, sub); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -586,7 +627,7 @@ jniCheck::validate_class(thr, sup, true); ) jboolean result = UNCHECKED()->IsAssignableFrom(env, sub, sup); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -601,7 +642,7 @@ ) jobject result = UNCHECKED()->ToReflectedField(env, cls, fieldID, isStatic); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -619,7 +660,7 @@ } ) jint result = UNCHECKED()->Throw(env, obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -634,15 +675,16 @@ jniCheck::validate_throwable_klass(thr, k); ) jint result = UNCHECKED()->ThrowNew(env, clazz, msg); - functionExit(env); + functionExit(thr); return result; JNI_END JNI_ENTRY_CHECKED(jthrowable, checked_jni_ExceptionOccurred(JNIEnv *env)) + thr->clear_pending_jni_exception_check(); functionEnterExceptionAllowed(thr); jthrowable result = UNCHECKED()->ExceptionOccurred(env); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -650,22 +692,24 @@ checked_jni_ExceptionDescribe(JNIEnv *env)) functionEnterExceptionAllowed(thr); UNCHECKED()->ExceptionDescribe(env); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, checked_jni_ExceptionClear(JNIEnv *env)) + thr->clear_pending_jni_exception_check(); functionEnterExceptionAllowed(thr); UNCHECKED()->ExceptionClear(env); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, checked_jni_FatalError(JNIEnv *env, const char *msg)) + thr->clear_pending_jni_exception_check(); functionEnter(thr); UNCHECKED()->FatalError(env, msg); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jint, @@ -675,7 +719,10 @@ if (capacity < 0) NativeReportJNIFatalError(thr, "negative capacity"); jint result = UNCHECKED()->PushLocalFrame(env, capacity); - functionExit(env); + if (result == JNI_OK) { + thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); + } + functionExit(thr); return result; JNI_END @@ -684,7 +731,7 @@ jobject result)) functionEnterExceptionAllowed(thr); jobject res = UNCHECKED()->PopLocalFrame(env, result); - functionExit(env); + functionExit(thr); return res; JNI_END @@ -698,7 +745,7 @@ } ) jobject result = UNCHECKED()->NewGlobalRef(env,lobj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -714,7 +761,7 @@ } ) UNCHECKED()->DeleteGlobalRef(env,gref); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -729,7 +776,7 @@ "Invalid local JNI handle passed to DeleteLocalRef"); ) UNCHECKED()->DeleteLocalRef(env, obj); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jboolean, @@ -750,7 +797,7 @@ } ) jboolean result = UNCHECKED()->IsSameObject(env,obj1,obj2); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -764,7 +811,7 @@ } ) jobject result = UNCHECKED()->NewLocalRef(env, ref); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -776,7 +823,10 @@ NativeReportJNIFatalError(thr, "negative capacity"); } jint result = UNCHECKED()->EnsureLocalCapacity(env, capacity); - functionExit(env); + if (result == JNI_OK) { + thr->active_handles()->set_planned_capacity(capacity + CHECK_JNI_LOCAL_REF_CAP_WARN_THRESHOLD); + } + functionExit(thr); return result; JNI_END @@ -788,7 +838,7 @@ jniCheck::validate_class(thr, clazz, false); ) jobject result = UNCHECKED()->AllocObject(env,clazz); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -806,7 +856,7 @@ va_start(args, methodID); jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); va_end(args); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -821,7 +871,7 @@ jniCheck::validate_jmethod_id(thr, methodID); ) jobject result = UNCHECKED()->NewObjectV(env,clazz,methodID,args); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -836,7 +886,7 @@ jniCheck::validate_jmethod_id(thr, methodID); ) jobject result = UNCHECKED()->NewObjectA(env,clazz,methodID,args); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -848,7 +898,7 @@ jniCheck::validate_object(thr, obj); ) jclass result = UNCHECKED()->GetObjectClass(env,obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -862,7 +912,7 @@ jniCheck::validate_class(thr, clazz, true); ) jboolean result = UNCHECKED()->IsInstanceOf(env,obj,clazz); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -876,7 +926,7 @@ jniCheck::validate_class(thr, clazz, false); ) jmethodID result = UNCHECKED()->GetMethodID(env,clazz,name,sig); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -895,7 +945,8 @@ ResultType result =UNCHECKED()->Call##Result##MethodV(env, obj, methodID, \ args); \ va_end(args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("Call"#Result"Method"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -910,7 +961,8 @@ ) \ ResultType result = UNCHECKED()->Call##Result##MethodV(env, obj, methodID,\ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("Call"#Result"MethodV"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -925,7 +977,8 @@ ) \ ResultType result = UNCHECKED()->Call##Result##MethodA(env, obj, methodID,\ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("Call"#Result"MethodA"); \ + functionExit(thr); \ return result; \ JNI_END @@ -952,7 +1005,8 @@ va_start(args,methodID); UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); va_end(args); - functionExit(env); + thr->set_pending_jni_exception_check("CallVoidMethod"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -965,7 +1019,8 @@ jniCheck::validate_call_object(thr, obj, methodID); ) UNCHECKED()->CallVoidMethodV(env,obj,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallVoidMethodV"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -978,7 +1033,8 @@ jniCheck::validate_call_object(thr, obj, methodID); ) UNCHECKED()->CallVoidMethodA(env,obj,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallVoidMethodA"); + functionExit(thr); JNI_END #define WRAPPER_CallNonvirtualMethod(ResultType, Result) \ @@ -1001,7 +1057,8 @@ methodID,\ args); \ va_end(args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"Method"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -1021,7 +1078,8 @@ clazz, \ methodID,\ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodV"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -1041,7 +1099,8 @@ clazz, \ methodID,\ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallNonvirtual"#Result"MethodA"); \ + functionExit(thr); \ return result; \ JNI_END @@ -1070,7 +1129,8 @@ va_start(args,methodID); UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); va_end(args); - functionExit(env); + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethod"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -1085,7 +1145,8 @@ jniCheck::validate_call_class(thr, clazz, methodID); ) UNCHECKED()->CallNonvirtualVoidMethodV(env,obj,clazz,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodV"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -1100,7 +1161,8 @@ jniCheck::validate_call_class(thr, clazz, methodID); ) UNCHECKED()->CallNonvirtualVoidMethodA(env,obj,clazz,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallNonvirtualVoidMethodA"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jfieldID, @@ -1113,7 +1175,7 @@ jniCheck::validate_class(thr, clazz, false); ) jfieldID result = UNCHECKED()->GetFieldID(env,clazz,name,sig); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1127,7 +1189,7 @@ checkInstanceFieldID(thr, fieldID, obj, FieldType); \ ) \ ReturnType result = UNCHECKED()->Get##Result##Field(env,obj,fieldID); \ - functionExit(env); \ + functionExit(thr); \ return result; \ JNI_END @@ -1152,7 +1214,7 @@ checkInstanceFieldID(thr, fieldID, obj, FieldType); \ ) \ UNCHECKED()->Set##Result##Field(env,obj,fieldID,val); \ - functionExit(env); \ + functionExit(thr); \ JNI_END WRAPPER_SetField(jobject, Object, T_OBJECT) @@ -1176,7 +1238,7 @@ jniCheck::validate_class(thr, clazz, false); ) jmethodID result = UNCHECKED()->GetStaticMethodID(env,clazz,name,sig); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1198,7 +1260,8 @@ methodID, \ args); \ va_end(args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallStatic"#Result"Method"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -1216,7 +1279,8 @@ clazz, \ methodID, \ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallStatic"#Result"MethodV"); \ + functionExit(thr); \ return result; \ JNI_END \ \ @@ -1234,7 +1298,8 @@ clazz, \ methodID, \ args); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("CallStatic"#Result"MethodA"); \ + functionExit(thr); \ return result; \ JNI_END @@ -1262,7 +1327,8 @@ va_start(args,methodID); UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); va_end(args); - functionExit(env); + thr->set_pending_jni_exception_check("CallStaticVoidMethod"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -1276,7 +1342,8 @@ jniCheck::validate_class(thr, cls, false); ) UNCHECKED()->CallStaticVoidMethodV(env,cls,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallStaticVoidMethodV"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -1290,7 +1357,8 @@ jniCheck::validate_class(thr, cls, false); ) UNCHECKED()->CallStaticVoidMethodA(env,cls,methodID,args); - functionExit(env); + thr->set_pending_jni_exception_check("CallStaticVoidMethodA"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jfieldID, @@ -1303,7 +1371,7 @@ jniCheck::validate_class(thr, clazz, false); ) jfieldID result = UNCHECKED()->GetStaticFieldID(env,clazz,name,sig); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1320,7 +1388,7 @@ ReturnType result = UNCHECKED()->GetStatic##Result##Field(env, \ clazz, \ fieldID); \ - functionExit(env); \ + functionExit(thr); \ return result; \ JNI_END @@ -1346,7 +1414,7 @@ checkStaticFieldID(thr, fieldID, clazz, FieldType); \ ) \ UNCHECKED()->SetStatic##Result##Field(env,clazz,fieldID,value); \ - functionExit(env); \ + functionExit(thr); \ JNI_END WRAPPER_SetStaticField(jobject, Object, T_OBJECT) @@ -1366,7 +1434,7 @@ jsize len)) functionEnter(thr); jstring result = UNCHECKED()->NewString(env,unicode,len); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1378,7 +1446,7 @@ checkString(thr, str); ) jsize result = UNCHECKED()->GetStringLength(env,str); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1407,7 +1475,7 @@ // Note that the dtrace arguments for the allocated memory will not match up with this solution. FreeHeap((char*)result); } - functionExit(env); + functionExit(thr); return new_result; JNI_END @@ -1442,7 +1510,7 @@ UNCHECKED()->ReleaseStringChars(env, str, (const jchar*) guarded.release_for_freeing()); } - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jstring, @@ -1450,7 +1518,7 @@ const char *utf)) functionEnter(thr); jstring result = UNCHECKED()->NewStringUTF(env,utf); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1462,7 +1530,7 @@ checkString(thr, str); ) jsize result = UNCHECKED()->GetStringUTFLength(env,str); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1490,7 +1558,7 @@ // Note that the dtrace arguments for the allocated memory will not match up with this solution. FreeHeap((char*)result, mtInternal); } - functionExit(env); + functionExit(thr); return new_result; JNI_END @@ -1525,7 +1593,7 @@ UNCHECKED()->ReleaseStringUTFChars(env, str, (const char*) guarded.release_for_freeing()); } - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jsize, @@ -1536,7 +1604,7 @@ check_is_array(thr, array); ) jsize result = UNCHECKED()->GetArrayLength(env,array); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1547,7 +1615,7 @@ jobject init)) functionEnter(thr); jobjectArray result = UNCHECKED()->NewObjectArray(env,len,clazz,init); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1560,7 +1628,8 @@ check_is_obj_array(thr, array); ) jobject result = UNCHECKED()->GetObjectArrayElement(env,array,index); - functionExit(env); + thr->set_pending_jni_exception_check("GetObjectArrayElement"); + functionExit(thr); return result; JNI_END @@ -1574,7 +1643,8 @@ check_is_obj_array(thr, array); ) UNCHECKED()->SetObjectArrayElement(env,array,index,val); - functionExit(env); + thr->set_pending_jni_exception_check("SetObjectArrayElement"); + functionExit(thr); JNI_END #define WRAPPER_NewScalarArray(Return, Result) \ @@ -1583,7 +1653,7 @@ jsize len)) \ functionEnter(thr); \ Return result = UNCHECKED()->New##Result##Array(env,len); \ - functionExit(env); \ + functionExit(thr); \ return (Return) result; \ JNI_END @@ -1611,7 +1681,7 @@ if (result != NULL) { \ result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \ } \ - functionExit(env); \ + functionExit(thr); \ return result; \ JNI_END @@ -1639,7 +1709,7 @@ ElementType* orig_result = (ElementType *) check_wrapped_array_release( \ thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \ UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \ - functionExit(env); \ + functionExit(thr); \ JNI_END WRAPPER_ReleaseScalarArrayElements(T_BOOLEAN,jboolean, Boolean, bool) @@ -1663,7 +1733,8 @@ check_primitive_array_type(thr, array, ElementTag); \ ) \ UNCHECKED()->Get##Result##ArrayRegion(env,array,start,len,buf); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("Get"#Result"ArrayRegion"); \ + functionExit(thr); \ JNI_END WRAPPER_GetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) @@ -1687,7 +1758,8 @@ check_primitive_array_type(thr, array, ElementTag); \ ) \ UNCHECKED()->Set##Result##ArrayRegion(env,array,start,len,buf); \ - functionExit(env); \ + thr->set_pending_jni_exception_check("Set"#Result"ArrayRegion"); \ + functionExit(thr); \ JNI_END WRAPPER_SetScalarArrayRegion(T_BOOLEAN, jboolean, Boolean) @@ -1706,7 +1778,7 @@ jint nMethods)) functionEnter(thr); jint result = UNCHECKED()->RegisterNatives(env,clazz,methods,nMethods); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1715,7 +1787,7 @@ jclass clazz)) functionEnter(thr); jint result = UNCHECKED()->UnregisterNatives(env,clazz); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1727,7 +1799,7 @@ jniCheck::validate_object(thr, obj); ) jint result = UNCHECKED()->MonitorEnter(env,obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1739,7 +1811,7 @@ jniCheck::validate_object(thr, obj); ) jint result = UNCHECKED()->MonitorExit(env,obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1748,7 +1820,7 @@ JavaVM **vm)) functionEnter(thr); jint result = UNCHECKED()->GetJavaVM(env,vm); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1763,7 +1835,8 @@ checkString(thr, str); ) UNCHECKED()->GetStringRegion(env, str, start, len, buf); - functionExit(env); + thr->set_pending_jni_exception_check("GetStringRegion"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void, @@ -1777,7 +1850,8 @@ checkString(thr, str); ) UNCHECKED()->GetStringUTFRegion(env, str, start, len, buf); - functionExit(env); + thr->set_pending_jni_exception_check("GetStringUTFRegion"); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(void *, @@ -1792,7 +1866,7 @@ if (result != NULL) { result = check_jni_wrap_copy_array(thr, array, result); } - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1808,7 +1882,7 @@ // Check the element array... void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode); UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(const jchar*, @@ -1820,7 +1894,7 @@ checkString(thr, string); ) const jchar *result = UNCHECKED()->GetStringCritical(env, string, isCopy); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1836,7 +1910,7 @@ * string parameter as a minor sanity check */ UNCHECKED()->ReleaseStringCritical(env, str, chars); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jweak, @@ -1849,7 +1923,7 @@ } ) jweak result = UNCHECKED()->NewWeakGlobalRef(env, obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1858,14 +1932,15 @@ jweak ref)) functionEnterExceptionAllowed(thr); UNCHECKED()->DeleteWeakGlobalRef(env, ref); - functionExit(env); + functionExit(thr); JNI_END JNI_ENTRY_CHECKED(jboolean, checked_jni_ExceptionCheck(JNIEnv *env)) + thr->clear_pending_jni_exception_check(); functionEnterExceptionAllowed(thr); jboolean result = UNCHECKED()->ExceptionCheck(env); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1875,7 +1950,7 @@ jlong capacity)) functionEnter(thr); jobject result = UNCHECKED()->NewDirectByteBuffer(env, address, capacity); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1884,7 +1959,7 @@ jobject buf)) functionEnter(thr); void* result = UNCHECKED()->GetDirectBufferAddress(env, buf); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1893,7 +1968,7 @@ jobject buf)) functionEnter(thr); jlong result = UNCHECKED()->GetDirectBufferCapacity(env, buf); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1906,7 +1981,7 @@ jniCheck::validate_object(thr, obj); ) jobjectRefType result = UNCHECKED()->GetObjectRefType(env, obj); - functionExit(env); + functionExit(thr); return result; JNI_END @@ -1915,7 +1990,7 @@ checked_jni_GetVersion(JNIEnv *env)) functionEnter(thr); jint result = UNCHECKED()->GetVersion(env); - functionExit(env); + functionExit(thr); return result; JNI_END diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/arguments.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -1572,7 +1572,7 @@ void Arguments::select_gc() { if (!gc_selected()) { - ArgumentsExt::select_gc_ergonomically(); + select_gc_ergonomically(); } } @@ -2067,7 +2067,7 @@ } // Check consistency of GC selection -bool Arguments::check_gc_consistency_user() { +bool Arguments::check_gc_consistency() { check_gclog_consistency(); bool status = true; // Ensure that the user has not selected conflicting sets @@ -2233,7 +2233,7 @@ FLAG_SET_DEFAULT(UseGCOverheadLimit, false); } - status = status && check_gc_consistency_user(); + status = status && check_gc_consistency(); status = status && check_stack_pages(); if (CMSIncrementalMode) { @@ -4006,7 +4006,7 @@ set_shared_spaces_flags(); // Check the GC selections again. - if (!ArgumentsExt::check_gc_consistency_ergo()) { + if (!check_gc_consistency()) { return JNI_EINVAL; } diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/arguments.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -466,8 +466,7 @@ static bool verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio); // Check for consistency in the selection of the garbage collector. - static bool check_gc_consistency_user(); // Check user-selected gc - static inline bool check_gc_consistency_ergo(); // Check ergonomic-selected gc + static bool check_gc_consistency(); // Check user-selected gc static void check_deprecated_gcs(); static void check_deprecated_gc_flags(); // Check consistecy or otherwise of VM argument settings @@ -615,8 +614,4 @@ UseParNewGC || UseSerialGC; } -bool Arguments::check_gc_consistency_ergo() { - return check_gc_consistency_user(); -} - #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/arguments_ext.hpp --- a/src/share/vm/runtime/arguments_ext.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/arguments_ext.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -30,22 +30,12 @@ class ArgumentsExt: AllStatic { public: - static inline void select_gc_ergonomically(); static inline void set_gc_specific_flags(); - static inline bool check_gc_consistency_ergo(); static void process_options(const JavaVMInitArgs* args) {} }; -void ArgumentsExt::select_gc_ergonomically() { - Arguments::select_gc_ergonomically(); -} - void ArgumentsExt::set_gc_specific_flags() { Arguments::set_gc_specific_flags(); } -bool ArgumentsExt::check_gc_consistency_ergo() { - return Arguments::check_gc_consistency_ergo(); -} - #endif // SHARE_VM_RUNTIME_ARGUMENTS_EXT_HPP diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/jniHandles.cpp --- a/src/share/vm/runtime/jniHandles.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/jniHandles.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -296,6 +296,7 @@ block->_top = 0; block->_next = NULL; block->_pop_frame_link = NULL; + block->_planned_capacity = block_size_in_oops; // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle debug_only(block->_last = NULL); debug_only(block->_free_list = NULL); @@ -529,6 +530,12 @@ return result; } +const size_t JNIHandleBlock::get_number_of_live_handles() { + CountHandleClosure counter; + oops_do(&counter); + return counter.count(); +} + // This method is not thread-safe, i.e., must be called whule holding a lock on the // structure. long JNIHandleBlock::memory_usage() const { diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/jniHandles.hpp --- a/src/share/vm/runtime/jniHandles.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/jniHandles.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -112,6 +112,9 @@ oop* _free_list; // Handle free list int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list + // Check JNI, "planned capacity" for current frame (or push/ensure) + size_t _planned_capacity; + #ifndef PRODUCT JNIHandleBlock* _block_list_link; // Link for list below static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) @@ -152,6 +155,11 @@ // Traversal of weak handles. Unreachable oops are cleared. void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); + // Checked JNI support + void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; } + const size_t get_planned_capacity() { return _planned_capacity; } + const size_t get_number_of_live_handles(); + // Debugging bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle bool contains(jobject handle) const; // Does this block contain handle diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/thread.cpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -1465,6 +1465,7 @@ _thread_stat = new ThreadStatistics(); _blocked_on_compilation = false; _jni_active_critical = 0; + _pending_jni_exception_check_fn = NULL; _do_not_unlock_if_synchronized = false; _cached_monitor_info = NULL; _parker = Parker::Allocate(this) ; diff -r 7619adc72abd -r 6d817035633c src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/runtime/thread.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -926,6 +926,9 @@ // support for JNI critical regions jint _jni_active_critical; // count of entries into JNI critical region + // Checked JNI: function name requires exception check + char* _pending_jni_exception_check_fn; + // For deadlock detection. int _depth_first_number; @@ -1408,6 +1411,12 @@ assert(_jni_active_critical >= 0, "JNI critical nesting problem?"); } + // Checked JNI, is the programmer required to check for exceptions, specify which function name + bool is_pending_jni_exception_check() const { return _pending_jni_exception_check_fn != NULL; } + void clear_pending_jni_exception_check() { _pending_jni_exception_check_fn = NULL; } + const char* get_pending_jni_exception_check() const { return _pending_jni_exception_check_fn; } + void set_pending_jni_exception_check(const char* fn_name) { _pending_jni_exception_check_fn = (char*) fn_name; } + // For deadlock detection int depth_first_number() { return _depth_first_number; } void set_depth_first_number(int dfn) { _depth_first_number = dfn; } diff -r 7619adc72abd -r 6d817035633c src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Tue Mar 03 13:06:16 2015 -0800 +++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Thu Mar 12 17:45:27 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -33,7 +33,9 @@ # include +#define __USE_LEGACY_PROTOTYPES__ # include +#undef __USE_LEGACY_PROTOTYPES__ # include # include // for bsd'isms # include diff -r 7619adc72abd -r 6d817035633c test/compiler/escapeAnalysis/TestEscapeThroughInvoke.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/escapeAnalysis/TestEscapeThroughInvoke.java Thu Mar 12 17:45:27 2015 -0400 @@ -0,0 +1,74 @@ +/* + * 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 + * @bug 8073956 + * @summary Tests C2 EA with allocated object escaping through a call. + * @run main/othervm -XX:CompileCommand=dontinline,TestEscapeThroughInvoke::create TestEscapeThroughInvoke + */ +public class TestEscapeThroughInvoke { + private A a; + + public static void main(String[] args) { + TestEscapeThroughInvoke test = new TestEscapeThroughInvoke(); + test.a = new A(42); + // Make sure run gets compiled by C2 + for (int i = 0; i < 100_000; ++i) { + test.run(); + } + } + + private void run() { + // Allocate something to trigger EA + new Object(); + // Create a new escaping instance of A and + // verify that it is always equal to 'a.saved'. + A escapingA = create(42); + a.check(escapingA); + } + + // Create and return a new instance of A that escaped through 'A::saveInto'. + // The 'dummy' parameters are needed to avoid EA skipping the methods. + private A create(Integer dummy) { + A result = new A(dummy); + result.saveInto(a, dummy); // result escapes into 'a' here + return result; + } +} + +class A { + private A saved; + + public A(Integer dummy) { } + + public void saveInto(A other, Integer dummy) { + other.saved = this; + } + + public void check(A other) { + if (this.saved != other) { + throw new RuntimeException("TEST FAILED: Objects not equal."); + } + } +}