# HG changeset patch # User bharadwaj # Date 1365120094 25200 # Node ID 0ca3dd0ffabaa92c68194b0926eb909c89cd4204 # Parent 0c039865ef2bd95aa2f9cc68dca160f0ccea0460# Parent bab5cbf74b5fdb27364bae5da39edb94adf1b967 Merge diff -r bab5cbf74b5f -r 0ca3dd0ffaba agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Thu Apr 04 12:18:46 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Thu Apr 04 17:01:34 2013 -0700 @@ -572,9 +572,14 @@ DTFWHome = sysRoot + File.separator + ".." + File.separator + "Program Files" + File.separator + "Debugging Tools For Windows"; searchList.add(DTFWHome); - searchList.add(DTFWHome + " (x86)"); - searchList.add(DTFWHome + " (x64)"); + // Only add the search path for the current CPU architecture: + String cpu = PlatformInfo.getCPU(); + if (cpu.equals("x86")) { + searchList.add(DTFWHome + " (x86)"); + } else if (cpu.equals("amd64")) { + searchList.add(DTFWHome + " (x64)"); + } // The last place to search is the system directory: searchList.add(sysRoot + File.separator + "system32"); } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -167,20 +167,6 @@ return Bsd::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { -#ifdef _LP64 - return size; -#else - julong result = MIN2(size, (julong)3800*M); - if (!is_allocatable(result)) { - // See comments under solaris for alignment considerations - julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); - result = MIN2(size, reasonable_size); - } - return result; -#endif // _LP64 -} - //////////////////////////////////////////////////////////////////////////////// // environment support diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -194,20 +194,6 @@ return Linux::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { -#ifdef _LP64 - return size; -#else - julong result = MIN2(size, (julong)3800*M); - if (!is_allocatable(result)) { - // See comments under solaris for alignment considerations - julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); - result = MIN2(size, reasonable_size); - } - return result; -#endif // _LP64 -} - //////////////////////////////////////////////////////////////////////////////// // environment support diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/os/posix/vm/os_posix.cpp --- a/src/os/posix/vm/os_posix.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/os/posix/vm/os_posix.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -188,4 +188,66 @@ st->cr(); } +bool os::has_allocatable_memory_limit(julong* limit) { + struct rlimit rlim; + int getrlimit_res = getrlimit(RLIMIT_AS, &rlim); + // if there was an error when calling getrlimit, assume that there is no limitation + // on virtual memory. + bool result; + if ((getrlimit_res != 0) || (rlim.rlim_cur == RLIM_INFINITY)) { + result = false; + } else { + *limit = (julong)rlim.rlim_cur; + result = true; + } +#ifdef _LP64 + return result; +#else + // arbitrary virtual space limit for 32 bit Unices found by testing. If + // getrlimit above returned a limit, bound it with this limit. Otherwise + // directly use it. + const julong max_virtual_limit = (julong)3800*M; + if (result) { + *limit = MIN2(*limit, max_virtual_limit); + } else { + *limit = max_virtual_limit; + } + // bound by actually allocatable memory. The algorithm uses two bounds, an + // upper and a lower limit. The upper limit is the current highest amount of + // memory that could not be allocated, the lower limit is the current highest + // amount of memory that could be allocated. + // The algorithm iteratively refines the result by halving the difference + // between these limits, updating either the upper limit (if that value could + // not be allocated) or the lower limit (if the that value could be allocated) + // until the difference between these limits is "small". + + // the minimum amount of memory we care about allocating. + const julong min_allocation_size = M; + + julong upper_limit = *limit; + + // first check a few trivial cases + if (is_allocatable(upper_limit) || (upper_limit <= min_allocation_size)) { + *limit = upper_limit; + } else if (!is_allocatable(min_allocation_size)) { + // we found that not even min_allocation_size is allocatable. Return it + // anyway. There is no point to search for a better value any more. + *limit = min_allocation_size; + } else { + // perform the binary search. + julong lower_limit = min_allocation_size; + while ((upper_limit - lower_limit) > min_allocation_size) { + julong temp_limit = ((upper_limit - lower_limit) / 2) + lower_limit; + temp_limit = align_size_down_(temp_limit, min_allocation_size); + if (is_allocatable(temp_limit)) { + lower_limit = temp_limit; + } else { + upper_limit = temp_limit; + } + } + *limit = lower_limit; + } + return true; +#endif +} diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -476,24 +476,6 @@ return Solaris::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { -#ifdef _LP64 - return size; -#else - julong result = MIN2(size, (julong)3835*M); - if (!is_allocatable(result)) { - // Memory allocations will be aligned but the alignment - // is not known at this point. Alignments will - // be at most to LargePageSizeInBytes. Protect - // allocations from alignments up to illegal - // values. If at this point 2G is illegal. - julong reasonable_size = (julong)2*G - 2 * LargePageSizeInBytes; - result = MIN2(size, reasonable_size); - } - return result; -#endif -} - static hrtime_t first_hrtime = 0; static const hrtime_t hrtime_hz = 1000*1000*1000; const int LOCK_BUSY = 1; diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/os/windows/vm/os_windows.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -686,12 +686,17 @@ return win32::physical_memory(); } -julong os::allocatable_physical_memory(julong size) { +bool os::has_allocatable_memory_limit(julong* limit) { + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); #ifdef _LP64 - return size; + *limit = (julong)ms.ullAvailVirtual; + return true; #else // Limit to 1400m because of the 2gb address space wall - return MIN2(size, (julong)1400*M); + *limit = MIN2((julong)1400*M, (julong)ms.ullAvailVirtual); + return true; #endif } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/classfile/symbolTable.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -677,9 +677,14 @@ ResourceMark rm; int length; jchar* chars = symbol->as_unicode(length); - unsigned int hashValue = hash_string(chars, length); - int index = the_table()->hash_to_index(hashValue); - return the_table()->lookup(index, chars, length, hashValue); + return lookup(chars, length); +} + + +oop StringTable::lookup(jchar* name, int len) { + unsigned int hash = hash_string(name, len); + int index = the_table()->hash_to_index(hash); + return the_table()->lookup(index, name, len, hash); } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/classfile/symbolTable.hpp --- a/src/share/vm/classfile/symbolTable.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/classfile/symbolTable.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -287,6 +287,7 @@ // Probing static oop lookup(Symbol* symbol); + static oop lookup(jchar* chars, int length); // Interning static oop intern(Symbol* symbol, TRAPS); diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -827,13 +827,28 @@ // We didn't go as far as Klass::restore_unshareable_info(), // so nothing to clean up. } else { - MutexLocker mu(SystemDictionary_lock, THREAD); - Klass* kk = find_class(name, ik->class_loader_data()); + Klass *kk; + { + MutexLocker mu(SystemDictionary_lock, THREAD); + kk = find_class(name, ik->class_loader_data()); + } if (kk != NULL) { // No clean up is needed if the shared class has been entered // into system dictionary, as load_shared_class() won't be called // again. } else { + // This must be done outside of the SystemDictionary_lock to + // avoid deadlock. + // + // Note that Klass::restore_unshareable_info (called via + // load_instance_class above) is also called outside + // of SystemDictionary_lock. Other threads are blocked from + // loading this class because they are waiting on the + // SystemDictionary_lock until this thread removes + // the placeholder below. + // + // This need to be re-thought when parallel-capable non-boot + // classloaders are supported by CDS (today they're not). clean_up_shared_class(ik, class_loader, THREAD); } } @@ -2196,10 +2211,9 @@ // Make sure all class components (including arrays) in the given // signature will be resolved to the same class in both loaders. // Returns the name of the type that failed a loader constraint check, or -// NULL if no constraint failed. The returned C string needs cleaning up -// with a ResourceMark in the caller. No exception except OOME is thrown. +// NULL if no constraint failed. No exception except OOME is thrown. // Arrays are not added to the loader constraint table, their elements are. -char* SystemDictionary::check_signature_loaders(Symbol* signature, +Symbol* SystemDictionary::check_signature_loaders(Symbol* signature, Handle loader1, Handle loader2, bool is_method, TRAPS) { // Nothing to do if loaders are the same. @@ -2207,14 +2221,12 @@ return NULL; } - ResourceMark rm(THREAD); SignatureStream sig_strm(signature, is_method); while (!sig_strm.is_done()) { if (sig_strm.is_object()) { - Symbol* s = sig_strm.as_symbol(CHECK_NULL); - Symbol* sig = s; + Symbol* sig = sig_strm.as_symbol(CHECK_NULL); if (!add_loader_constraint(sig, loader1, loader2, THREAD)) { - return sig->as_C_string(); + return sig; } } sig_strm.next(); diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -485,8 +485,8 @@ // Check class loader constraints static bool add_loader_constraint(Symbol* name, Handle loader1, Handle loader2, TRAPS); - static char* check_signature_loaders(Symbol* signature, Handle loader1, - Handle loader2, bool is_method, TRAPS); + static Symbol* check_signature_loaders(Symbol* signature, Handle loader1, + Handle loader2, bool is_method, TRAPS); // JSR 292 // find a java.lang.invoke.MethodHandle.invoke* method for a given signature diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -854,7 +854,8 @@ assert(!isHumongous(word_size), "we do not allow humongous TLABs"); unsigned int dummy_gc_count_before; - return attempt_allocation(word_size, &dummy_gc_count_before); + int dummy_gclocker_retry_count = 0; + return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count); } HeapWord* @@ -863,14 +864,14 @@ assert_heap_not_locked_and_not_at_safepoint(); // Loop until the allocation is satisified, or unsatisfied after GC. - for (int try_count = 1; /* we'll return */; try_count += 1) { + for (int try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { unsigned int gc_count_before; HeapWord* result = NULL; if (!isHumongous(word_size)) { - result = attempt_allocation(word_size, &gc_count_before); + result = attempt_allocation(word_size, &gc_count_before, &gclocker_retry_count); } else { - result = attempt_allocation_humongous(word_size, &gc_count_before); + result = attempt_allocation_humongous(word_size, &gc_count_before, &gclocker_retry_count); } if (result != NULL) { return result; @@ -894,6 +895,9 @@ } return result; } else { + if (gclocker_retry_count > GCLockerRetryAllocationCount) { + return NULL; + } assert(op.result() == NULL, "the result should be NULL if the VM op did not succeed"); } @@ -910,7 +914,8 @@ } HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, - unsigned int *gc_count_before_ret) { + unsigned int *gc_count_before_ret, + int* gclocker_retry_count_ret) { // Make sure you read the note in attempt_allocation_humongous(). assert_heap_not_locked_and_not_at_safepoint(); @@ -986,10 +991,16 @@ return NULL; } } else { + if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { + MutexLockerEx x(Heap_lock); + *gc_count_before_ret = total_collections(); + return NULL; + } // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GC_locker::stall_until_clear(); + (*gclocker_retry_count_ret) += 1; } // We can reach here if we were unsuccessul in scheduling a @@ -1019,7 +1030,8 @@ } HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, - unsigned int * gc_count_before_ret) { + unsigned int * gc_count_before_ret, + int* gclocker_retry_count_ret) { // The structure of this method has a lot of similarities to // attempt_allocation_slow(). The reason these two were not merged // into a single one is that such a method would require several "if @@ -1104,10 +1116,16 @@ return NULL; } } else { + if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { + MutexLockerEx x(Heap_lock); + *gc_count_before_ret = total_collections(); + return NULL; + } // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GC_locker::stall_until_clear(); + (*gclocker_retry_count_ret) += 1; } // We can reach here if we were unsuccessul in scheduling a @@ -3270,12 +3288,12 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { - if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) { + if (SafepointSynchronize::is_at_safepoint()) { if (!silent) { gclog_or_tty->print("Roots "); } VerifyRootsClosure rootsCl(vo); assert(Thread::current()->is_VM_thread(), - "Expected to be executed serially by the VM thread at this point"); + "Expected to be executed serially by the VM thread at this point"); CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false); VerifyKlassClosure klassCl(this, &rootsCl); @@ -3360,7 +3378,8 @@ } guarantee(!failures, "there should not have been any failures"); } else { - if (!silent) gclog_or_tty->print("(SKIPPING roots, heapRegions, remset) "); + if (!silent) + gclog_or_tty->print("(SKIPPING roots, heapRegionSets, heapRegions, remset) "); } } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -559,18 +559,21 @@ // the mutator alloc region without taking the Heap_lock. This // should only be used for non-humongous allocations. inline HeapWord* attempt_allocation(size_t word_size, - unsigned int* gc_count_before_ret); + unsigned int* gc_count_before_ret, + int* gclocker_retry_count_ret); // Second-level mutator allocation attempt: take the Heap_lock and // retry the allocation attempt, potentially scheduling a GC // pause. This should only be used for non-humongous allocations. HeapWord* attempt_allocation_slow(size_t word_size, - unsigned int* gc_count_before_ret); + unsigned int* gc_count_before_ret, + int* gclocker_retry_count_ret); // Takes the Heap_lock and attempts a humongous allocation. It can // potentially schedule a GC pause. HeapWord* attempt_allocation_humongous(size_t word_size, - unsigned int* gc_count_before_ret); + unsigned int* gc_count_before_ret, + int* gclocker_retry_count_ret); // Allocation attempt that should be called during safepoints (e.g., // at the end of a successful GC). expect_null_mutator_alloc_region diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -60,7 +60,8 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, - unsigned int* gc_count_before_ret) { + unsigned int* gc_count_before_ret, + int* gclocker_retry_count_ret) { assert_heap_not_locked_and_not_at_safepoint(); assert(!isHumongous(word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -68,7 +69,9 @@ HeapWord* result = _mutator_alloc_region.attempt_allocation(word_size, false /* bot_updates */); if (result == NULL) { - result = attempt_allocation_slow(word_size, gc_count_before_ret); + result = attempt_allocation_slow(word_size, + gc_count_before_ret, + gclocker_retry_count_ret); } assert_heap_not_locked(); if (result != NULL) { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -326,6 +326,7 @@ uint loop_count = 0; uint gc_count = 0; + int gclocker_stalled_count = 0; while (result == NULL) { // We don't want to have multiple collections for a single filled generation. @@ -354,6 +355,10 @@ return result; } + if (gclocker_stalled_count > GCLockerRetryAllocationCount) { + return NULL; + } + // Failed to allocate without a gc. if (GC_locker::is_active_and_needs_gc()) { // If this thread is not in a jni critical section, we stall @@ -366,6 +371,7 @@ if (!jthr->in_critical()) { MutexUnlocker mul(Heap_lock); GC_locker::stall_until_clear(); + gclocker_stalled_count += 1; continue; } else { if (CheckJNICalls) { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -256,7 +256,7 @@ } if (PrintGC && Verbose) { - if (success && GC_locker::is_active()) { + if (success && GC_locker::is_active_and_needs_gc()) { gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead"); } } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -458,25 +458,27 @@ Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); { ResourceMark rm(THREAD); - char* failed_type_name = + Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(method_signature, loader, class_loader, true, CHECK); - if (failed_type_name != NULL) { + if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving method" " \"%s\" the class loader (instance of %s) of the current class, %s," - " and the class loader (instance of %s) for resolved class, %s, have" + " and the class loader (instance of %s) for the method's defining class, %s, have" " different Class objects for the type %s used in the signature"; char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); const char* loader1 = SystemDictionary::loader_name(loader()); char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(class_loader()); - char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); + char* target = InstanceKlass::cast(resolved_method->method_holder()) + ->name()->as_C_string(); + char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + - strlen(current) + strlen(loader2) + strlen(resolved) + - strlen(failed_type_name); + strlen(current) + strlen(loader2) + strlen(target) + + strlen(failed_type_name) + 1; char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, - resolved, failed_type_name); + target, failed_type_name); THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); } } @@ -520,26 +522,28 @@ Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); { ResourceMark rm(THREAD); - char* failed_type_name = + Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(method_signature, loader, class_loader, true, CHECK); - if (failed_type_name != NULL) { + if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving " "interface method \"%s\" the class loader (instance of %s) of the " "current class, %s, and the class loader (instance of %s) for " - "resolved class, %s, have different Class objects for the type %s " + "the method's defining class, %s, have different Class objects for the type %s " "used in the signature"; char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); const char* loader1 = SystemDictionary::loader_name(loader()); char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(class_loader()); - char* resolved = InstanceKlass::cast(resolved_klass())->name()->as_C_string(); + char* target = InstanceKlass::cast(resolved_method->method_holder()) + ->name()->as_C_string(); + char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + - strlen(current) + strlen(loader2) + strlen(resolved) + - strlen(failed_type_name); + strlen(current) + strlen(loader2) + strlen(target) + + strlen(failed_type_name) + 1; char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, - resolved, failed_type_name); + target, failed_type_name); THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); } } @@ -642,12 +646,12 @@ Symbol* signature_ref = pool->signature_ref_at(index); { ResourceMark rm(THREAD); - char* failed_type_name = + Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(signature_ref, ref_loader, sel_loader, false, CHECK); - if (failed_type_name != NULL) { + if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving field" " \"%s\" the class loader (instance of %s) of the referring class, " "%s, and the class loader (instance of %s) for the field's resolved " @@ -656,8 +660,9 @@ const char* loader1 = SystemDictionary::loader_name(ref_loader()); char* sel = InstanceKlass::cast(sel_klass())->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(sel_loader()); + char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) + - strlen(sel) + strlen(loader2) + strlen(failed_type_name); + strlen(sel) + strlen(loader2) + strlen(failed_type_name) + 1; char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2, failed_type_name); diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/memory/collectorPolicy.cpp --- a/src/share/vm/memory/collectorPolicy.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/memory/collectorPolicy.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -532,7 +532,7 @@ // Loop until the allocation is satisified, // or unsatisfied after GC. - for (int try_count = 1; /* return or throw */; try_count += 1) { + for (int try_count = 1, gclocker_stalled_count = 0; /* return or throw */; try_count += 1) { HandleMark hm; // discard any handles allocated in each iteration // First allocation attempt is lock-free. @@ -576,6 +576,10 @@ } } + if (gclocker_stalled_count > GCLockerRetryAllocationCount) { + return NULL; // we didn't get to do a GC and we didn't get any memory + } + // If this thread is not in a jni critical section, we stall // the requestor until the critical section has cleared and // GC allowed. When the critical section clears, a GC is @@ -587,6 +591,7 @@ MutexUnlocker mul(Heap_lock); // Wait for JNI critical section to be exited GC_locker::stall_until_clear(); + gclocker_stalled_count += 1; continue; } else { if (CheckJNICalls) { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/memory/universe.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -953,15 +953,6 @@ void universe2_init() { EXCEPTION_MARK; Universe::genesis(CATCH); - // Although we'd like to verify here that the state of the heap - // is good, we can't because the main thread has not yet added - // itself to the threads list (so, using current interfaces - // we can't "fill" its TLAB), unless TLABs are disabled. - if (VerifyBeforeGC && !UseTLAB && - Universe::heap()->total_collections() >= VerifyGCStartAt) { - Universe::heap()->prepare_for_verify(); - Universe::verify(); // make sure we're starting with a clean slate - } } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/oops/constMethod.cpp --- a/src/share/vm/oops/constMethod.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/oops/constMethod.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -363,6 +363,26 @@ return (AnnotationArray**)constMethod_end() - offset; } +// copy annotations from 'cm' to 'this' +void ConstMethod::copy_annotations_from(ConstMethod* cm) { + if (cm->has_method_annotations()) { + assert(has_method_annotations(), "should be allocated already"); + set_method_annotations(cm->method_annotations()); + } + if (cm->has_parameter_annotations()) { + assert(has_parameter_annotations(), "should be allocated already"); + set_parameter_annotations(cm->parameter_annotations()); + } + if (cm->has_type_annotations()) { + assert(has_type_annotations(), "should be allocated already"); + set_type_annotations(cm->type_annotations()); + } + if (cm->has_default_annotations()) { + assert(has_default_annotations(), "should be allocated already"); + set_default_annotations(cm->default_annotations()); + } +} + // Printing void ConstMethod::print_on(outputStream* st) const { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/oops/constMethod.hpp --- a/src/share/vm/oops/constMethod.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/oops/constMethod.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -441,6 +441,9 @@ return has_default_annotations() ? default_annotations()->length() : 0; } + // Copy annotations from other ConstMethod + void copy_annotations_from(ConstMethod* cm); + // byte codes void set_code(address code) { if (code_size() > 0) { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/oops/klassVtable.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -327,11 +327,11 @@ if (target_loader() != super_loader()) { ResourceMark rm(THREAD); - char* failed_type_name = + Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(signature, target_loader, super_loader, true, CHECK_(false)); - if (failed_type_name != NULL) { + if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation: when resolving " "overridden method \"%s\" the class loader (instance" " of %s) of the current class, %s, and its superclass loader " @@ -341,6 +341,7 @@ const char* loader1 = SystemDictionary::loader_name(target_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(super_loader()); + char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + strlen(current) + strlen(loader2) + strlen(failed_type_name); char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); @@ -787,12 +788,12 @@ Handle method_holder_loader (THREAD, target->method_holder()->class_loader()); if (method_holder_loader() != interface_loader()) { ResourceMark rm(THREAD); - char* failed_type_name = + Symbol* failed_type_symbol = SystemDictionary::check_signature_loaders(method_signature, method_holder_loader, interface_loader, true, CHECK); - if (failed_type_name != NULL) { + if (failed_type_symbol != NULL) { const char* msg = "loader constraint violation in interface " "itable initialization: when resolving method \"%s\" the class" " loader (instance of %s) of the current class, %s, " @@ -804,6 +805,7 @@ char* current = klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(interface_loader()); char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string(); + char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + strlen(current) + strlen(loader2) + strlen(iface) + strlen(failed_type_name); diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/oops/method.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -1196,6 +1196,8 @@ newm->set_stackmap_data(stackmap_data); } + // copy annotations over to new method + newcm->copy_annotations_from(cm); return newm; } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/oops/symbol.cpp --- a/src/share/vm/oops/symbol.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/oops/symbol.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -162,7 +162,7 @@ const char *ptr = (const char *)&_body[0]; int quoted_length = UTF8::quoted_ascii_length(ptr, utf8_length()); char* result = NEW_RESOURCE_ARRAY(char, quoted_length + 1); - UTF8::as_quoted_ascii(ptr, result, quoted_length + 1); + UTF8::as_quoted_ascii(ptr, utf8_length(), result, quoted_length + 1); return result; } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/prims/whitebox.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -254,6 +254,24 @@ CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; WB_END +WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) + ResourceMark rm(THREAD); + int len; + jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len); + oop found_string = StringTable::the_table()->lookup(name, len); + if (found_string == NULL) { + return false; + } + return true; +WB_END + + +WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) + Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true); + Universe::heap()->collect(GCCause::_last_ditch_collection); +WB_END + + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -343,6 +361,8 @@ CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, {CC"getCompileQueuesSize", CC"()I", (void*)&WB_GetCompileQueuesSize}, + {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, + {CC"fullGC", CC"()V", (void*)&WB_FullGC }, }; #undef CC diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/arguments.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -1553,6 +1553,15 @@ } } +julong Arguments::limit_by_allocatable_memory(julong limit) { + julong max_allocatable; + julong result = limit; + if (os::has_allocatable_memory_limit(&max_allocatable)) { + result = MIN2(result, max_allocatable / MaxVirtMemFraction); + } + return result; +} + void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) { // Deprecated flag @@ -1591,12 +1600,12 @@ } reasonable_max = MIN2(reasonable_max, max_coop_heap); } - reasonable_max = os::allocatable_physical_memory(reasonable_max); + reasonable_max = limit_by_allocatable_memory(reasonable_max); if (!FLAG_IS_DEFAULT(InitialHeapSize)) { // An initial heap size was specified on the command line, // so be sure that the maximum size is consistent. Done - // after call to allocatable_physical_memory because that + // after call to limit_by_allocatable_memory because that // method might reduce the allocation size. reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize); } @@ -1616,14 +1625,14 @@ reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize); - reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum); + reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum); julong reasonable_initial = phys_mem / InitialRAMFraction; reasonable_initial = MAX2(reasonable_initial, reasonable_minimum); reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize); - reasonable_initial = os::allocatable_physical_memory(reasonable_initial); + reasonable_initial = limit_by_allocatable_memory(reasonable_initial); if (PrintGCDetails && Verbose) { // Cannot use gclog_or_tty yet. @@ -2609,9 +2618,7 @@ initHeapSize = MIN2(total_memory / (julong)2, total_memory - (julong)160*M); - // Make sure that if we have a lot of memory we cap the 32 bit - // process space. The 64bit VM version of this function is a nop. - initHeapSize = os::allocatable_physical_memory(initHeapSize); + initHeapSize = limit_by_allocatable_memory(initHeapSize); if (FLAG_IS_DEFAULT(MaxHeapSize)) { FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize); @@ -3320,6 +3327,13 @@ } check_deprecated_gcs(); check_deprecated_gc_flags(); + if (AssumeMP && !UseSerialGC) { + if (FLAG_IS_DEFAULT(ParallelGCThreads) && ParallelGCThreads == 1) { + warning("If the number of processors is expected to increase from one, then" + " you should configure the number of parallel GC threads appropriately" + " using -XX:ParallelGCThreads=N"); + } + } #else // INCLUDE_ALL_GCS assert(verify_serial_gc_flags(), "SerialGC unset"); #endif // INCLUDE_ALL_GCS diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/arguments.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -312,6 +312,9 @@ static void set_use_compressed_oops(); static void set_ergonomics_flags(); static void set_shared_spaces_flags(); + // limits the given memory size by the maximum amount of memory this process is + // currently allowed to allocate or reserve. + static julong limit_by_allocatable_memory(julong size); // Setup heap size static void set_heap_size(); // Based on automatic selection criteria, should the diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -457,6 +457,9 @@ lp64_product(intx, ObjectAlignmentInBytes, 8, \ "Default object alignment in bytes, 8 is minimum") \ \ + product(bool, AssumeMP, false, \ + "Instruct the VM to assume multiple processors are available") \ + \ /* UseMembar is theoretically a temp flag used for memory barrier \ * removal testing. It was supposed to be removed before FCS but has \ * been re-added (see 6401008) */ \ @@ -1404,6 +1407,10 @@ "How much the GC can expand the eden by while the GC locker " \ "is active (as a percentage)") \ \ + diagnostic(intx, GCLockerRetryAllocationCount, 2, \ + "Number of times to retry allocations when" \ + " blocked by the GC locker") \ + \ develop(bool, UseCMSAdaptiveFreeLists, true, \ "Use Adaptive Free Lists in the CMS generation") \ \ @@ -1960,6 +1967,10 @@ product(uintx, InitialRAMFraction, 64, \ "Fraction (1/n) of real memory used for initial heap size") \ \ + develop(uintx, MaxVirtMemFraction, 2, \ + "Maximum fraction (1/n) of virtual memory used for ergonomically" \ + "determining maximum heap size") \ + \ product(bool, UseAutoGCSelectPolicy, false, \ "Use automatic collection selection policy") \ \ diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/init.cpp --- a/src/share/vm/runtime/init.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/init.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -132,15 +132,6 @@ javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init - // Although we'd like to, we can't easily do a heap verify - // here because the main thread isn't yet a JavaThread, so - // its TLAB may not be made parseable from the usual interfaces. - if (VerifyBeforeGC && !UseTLAB && - Universe::heap()->total_collections() >= VerifyGCStartAt) { - Universe::heap()->prepare_for_verify(); - Universe::verify(); // make sure we're starting with a clean slate - } - // All the flags that get adjusted by VM_Version_init and os::init_2 // have been set so dump the flags now. if (PrintFlagsFinal) { diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/os.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -180,11 +180,11 @@ // Interface for detecting multiprocessor system static inline bool is_MP() { assert(_processor_count > 0, "invalid processor count"); - return _processor_count > 1; + return _processor_count > 1 || AssumeMP; } static julong available_memory(); static julong physical_memory(); - static julong allocatable_physical_memory(julong size); + static bool has_allocatable_memory_limit(julong* limit); static bool is_server_class_machine(); // number of CPUs diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/runtime/thread.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -3423,12 +3423,6 @@ // real raw monitor. VM is setup enough here for raw monitor enter. JvmtiExport::transition_pending_onload_raw_monitors(); - if (VerifyBeforeGC && - Universe::heap()->total_collections() >= VerifyGCStartAt) { - Universe::heap()->prepare_for_verify(); - Universe::verify(); // make sure we're starting with a clean slate - } - // Fully start NMT MemTracker::start(); @@ -3452,6 +3446,11 @@ } assert (Universe::is_fully_initialized(), "not initialized"); + if (VerifyBeforeGC && VerifyGCStartAt == 0) { + Universe::heap()->prepare_for_verify(); + Universe::verify(); // make sure we're starting with a clean slate + } + EXCEPTION_MARK; // At this point, the Universe is initialized, but we have not executed diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/services/memTracker.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -86,13 +86,13 @@ static inline void set_autoShutdown(bool value) { } static void shutdown(ShutdownReason reason) { } - static inline bool shutdown_in_progress() { } + static inline bool shutdown_in_progress() { return false; } static bool print_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true) { } + bool summary_only = true) { return false; } static bool compare_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true) { } + bool summary_only = true) { return false; } - static bool wbtest_wait_for_data_merge() { } + static bool wbtest_wait_for_data_merge() { return false; } static inline void sync() { } static inline void thread_exiting(JavaThread* thread) { } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/utilities/utf8.cpp --- a/src/share/vm/utilities/utf8.cpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/utilities/utf8.cpp Thu Apr 04 17:01:34 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -180,11 +180,12 @@ } // converts a utf8 string to quoted ascii -void UTF8::as_quoted_ascii(const char* utf8_str, char* buf, int buflen) { +void UTF8::as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen) { const char *ptr = utf8_str; + const char *utf8_end = ptr + utf8_length; char* p = buf; char* end = buf + buflen; - while (*ptr != '\0') { + while (ptr < utf8_end) { jchar c; ptr = UTF8::next(ptr, &c); if (c >= 32 && c < 127) { @@ -196,6 +197,7 @@ p += 6; } } + assert(p < end, "sanity"); *p = '\0'; } diff -r bab5cbf74b5f -r 0ca3dd0ffaba src/share/vm/utilities/utf8.hpp --- a/src/share/vm/utilities/utf8.hpp Thu Apr 04 12:18:46 2013 -0700 +++ b/src/share/vm/utilities/utf8.hpp Thu Apr 04 17:01:34 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -45,7 +45,7 @@ static int quoted_ascii_length(const char* utf8_str, int utf8_length); // converts a utf8 string to quoted ascii - static void as_quoted_ascii(const char* utf8_str, char* buf, int buflen); + static void as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int buflen); // converts a quoted ascii string to utf8 string. returns the original // string unchanged if nothing needs to be done. diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/gc/TestVerifyBeforeGCDuringStartup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestVerifyBeforeGCDuringStartup.java Thu Apr 04 17:01:34 2013 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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 TestVerifyBeforeGCDuringStartup.java + * @key gc + * @bug 8010463 + * @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463 + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestVerifyBeforeGCDuringStartup { + public static void main(String args[]) throws Exception { + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), + "-XX:-UseTLAB", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerifyBeforeGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[Verifying"); + output.shouldHaveExitValue(0); + } +} diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java --- a/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java Thu Apr 04 12:18:46 2013 -0700 +++ b/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java Thu Apr 04 17:01:34 2013 -0700 @@ -39,8 +39,10 @@ public static void main(String[] args) throws Exception { String pid = Integer.toString(ProcessTools.getProcessId()); - ProcessBuilder pb = new ProcessBuilder(); - pb.command(JDKToolFinder.getJDKTool("jmap"), "-heap", pid); + JDKToolLauncher jmap = JDKToolLauncher.create("jmap") + .addToolArg("-heap") + .addToolArg(pid); + ProcessBuilder pb = new ProcessBuilder(jmap.getCommand()); File out = new File("ClassMetaspaceSizeInJmapHeap.stdout.txt"); pb.redirectOutput(out); diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/runtime/7116786/Test7116786.java --- a/test/runtime/7116786/Test7116786.java Thu Apr 04 12:18:46 2013 -0700 +++ b/test/runtime/7116786/Test7116786.java Thu Apr 04 17:01:34 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -338,9 +338,12 @@ "invalid constant pool index in ldc", "Invalid index in ldc"), - new Case("case58", "verifier.cpp", true, "verify_switch", + /* No longer a valid test case for bytecode version >= 51. Nonzero + * padding bytes are permitted with lookupswitch and tableswitch + * bytecodes as of JVMS 3d edition */ + new Case("case58", "verifier.cpp", false, "verify_switch", "bad switch padding", - "Nonzero padding byte in lookswitch or tableswitch"), + "Nonzero padding byte in lookupswitch or tableswitch"), new Case("case59", "verifier.cpp", true, "verify_switch", "tableswitch low is greater than high", diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/runtime/interned/SanityTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/interned/SanityTest.java Thu Apr 04 17:01:34 2013 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, 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 SanityTest + * @summary Sanity check of String.intern() & GC + * @library /testlibrary /testlibrary/whitebox + * @build SanityTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SanityTest + */ + +import java.util.*; +import sun.hotspot.WhiteBox; + + +public class SanityTest { + public static Object tmp; + public static void main(String... args) { + + WhiteBox wb = WhiteBox.getWhiteBox(); + StringBuilder sb = new StringBuilder(); + sb.append("1234x"); sb.append("x56789"); + String str = sb.toString(); + + if (wb.isInStringTable(str)) { + throw new RuntimeException("String " + str + " is already interned"); + } + str.intern(); + if (!wb.isInStringTable(str)) { + throw new RuntimeException("String " + str + " is not interned"); + } + str = sb.toString(); + wb.fullGC(); + if (wb.isInStringTable(str)) { + throw new RuntimeException("String " + str + " is in StringTable even after GC"); + } + } +} diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Thu Apr 04 17:01:34 2013 -0700 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013, 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. + */ + +package com.oracle.java.testlibrary; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.ProcessTools; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the + * following code run {@code jmap -heap} against a process with GC logging + * turned on for the {@code jmap} process: + * + *
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ *                                       .addVMArg("-XX:+PrintGC");
+ *                                       .addVMArg("-XX:+PrintGCDetails")
+ *                                       .addToolArg("-heap")
+ *                                       .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * 
+ */ +public class JDKToolLauncher { + private final String executable; + private final List vmArgs = new ArrayList(); + private final List toolArgs = new ArrayList(); + + private JDKToolLauncher(String tool) { + executable = JDKToolFinder.getJDKTool(tool); + vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); + } + + /** + * Creates a new JDKToolLauncher for the specified tool. + * + * @param tool The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add("-J" + arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List command = new ArrayList(); + command.add(executable); + command.addAll(vmArgs); + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +} diff -r bab5cbf74b5f -r 0ca3dd0ffaba test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Thu Apr 04 12:18:46 2013 -0700 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Thu Apr 04 17:01:34 2013 -0700 @@ -94,4 +94,10 @@ public native int getMethodCompilationLevel(Method method); public native boolean setDontInlineMethod(Method method, boolean value); public native int getCompileQueuesSize(); + + //Intered strings + public native boolean isInStringTable(String str); + + // force Full GC + public native void fullGC(); }