# HG changeset patch # User coleenp # Date 1403190970 14400 # Node ID e3af4e02b0d5050a05dfb92f965204b5d840b3f3 # Parent c937c5e883c5b9969cbfdbcb65ef08c55a3ed8d6 8026977: NPG: Remove ConstantPool::lock Summary: Write klass and resolved_references constant pool fields lock free. Reviewed-by: jrose, twisti diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -512,24 +512,9 @@ } else { // Check if it's resolved if it's not a symbol constant pool entry. klass = KlassHandle(THREAD, ConstantPool::klass_at_if_loaded(cpool, index)); - + // Try to look it up by name. if (klass.is_null()) { - // The klass has not been inserted into the constant pool. - // Try to look it up by name. - { - // We have to lock the cpool to keep the oop from being resolved - // while we are accessing it. - MonitorLockerEx ml(cpool->lock()); - constantTag tag = cpool->tag_at(index); - if (tag.is_klass()) { - // The klass has been inserted into the constant pool - // very recently. - klass = KlassHandle(THREAD, cpool->resolved_klass_at(index)); - } else { - assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag"); - klass_name = cpool->unresolved_klass_at(index); - } - } + klass_name = cpool->klass_name_at(index); } } diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/ci/ciReplay.cpp --- a/hotspot/src/share/vm/ci/ciReplay.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciReplay.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2013, 2014, 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 @@ -686,7 +686,7 @@ switch (cp->tag_at(i).value()) { case JVM_CONSTANT_UnresolvedClass: { if (tag == JVM_CONSTANT_Class) { - tty->print_cr("Resolving klass %s at %d", cp->unresolved_klass_at(i)->as_utf8(), i); + tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i); Klass* k = cp->klass_at(i, CHECK); } break; diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -510,7 +510,7 @@ jbyte tag = cp->tag_at(index).value(); switch (tag) { case JVM_CONSTANT_UnresolvedClass: { - Symbol* class_name = cp->unresolved_klass_at(index); + Symbol* class_name = cp->klass_name_at(index); // check the name, even if _cp_patches will overwrite it verify_legal_class_name(class_name, CHECK_(nullHandle)); break; @@ -3161,7 +3161,7 @@ if (_need_verify) is_array = super_klass->oop_is_array(); } else if (_need_verify) { - is_array = (_cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY); + is_array = (_cp->klass_name_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY); } if (_need_verify) { guarantee_property(!is_array, @@ -3855,7 +3855,7 @@ "Invalid this class index %u in constant pool in class file %s", this_class_index, CHECK_(nullHandle)); - Symbol* class_name = cp->unresolved_klass_at(this_class_index); + Symbol* class_name = cp->klass_name_at(this_class_index); assert(class_name != NULL, "class_name can't be null"); // It's important to set parsed_name *before* resolving the super class. diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Jun 19 11:16:10 2014 -0400 @@ -187,8 +187,6 @@ JNIHandleBlock* handles() const; void set_handles(JNIHandleBlock* handles); - Mutex* metaspace_lock() const { return _metaspace_lock; } - // GC interface. void clear_claimed() { _claimed = 0; } bool claimed() const { return _claimed == 1; } @@ -216,6 +214,8 @@ return _the_null_class_loader_data; } + Mutex* metaspace_lock() const { return _metaspace_lock; } + bool is_anonymous() const { return _is_anonymous; } static void init_null_class_loader_data() { diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/oops/constantPool.cpp --- a/hotspot/src/share/vm/oops/constantPool.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -71,7 +71,6 @@ // only set to non-zero if constant pool is merged by RedefineClasses set_version(0); - set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); // initialize tag array int length = tags->length(); @@ -100,9 +99,6 @@ void ConstantPool::release_C_heap_structures() { // walk constant pool and decrement symbol reference counts unreference_symbols(); - - delete _lock; - set_lock(NULL); } objArrayOop ConstantPool::resolved_references() const { @@ -146,8 +142,7 @@ // CDS support. Create a new resolved_references array. void ConstantPool::restore_unshareable_info(TRAPS) { - // Only create the new resolved references array and lock if it hasn't been - // attempted before + // Only create the new resolved references array if it hasn't been attempted before if (resolved_references() != NULL) return; // restore the C++ vtable from the shared archive @@ -163,9 +158,6 @@ ClassLoaderData* loader_data = pool_holder()->class_loader_data(); set_resolved_references(loader_data->add_handle(refs_handle)); } - - // Also need to recreate the mutex. Make sure this matches the constructor - set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); } } @@ -176,7 +168,6 @@ set_resolved_reference_length( resolved_references() != NULL ? resolved_references()->length() : 0); set_resolved_references(NULL); - set_lock(NULL); } int ConstantPool::cp_to_object_index(int cp_index) { @@ -186,11 +177,41 @@ return (i < 0) ? _no_index_sentinel : i; } +void ConstantPool::trace_class_resolution(constantPoolHandle this_cp, KlassHandle k) { + ResourceMark rm; + int line_number = -1; + const char * source_file = NULL; + if (JavaThread::current()->has_last_Java_frame()) { + // try to identify the method which called this function. + vframeStream vfst(JavaThread::current()); + if (!vfst.at_end()) { + line_number = vfst.method()->line_number_from_bci(vfst.bci()); + Symbol* s = vfst.method()->method_holder()->source_file_name(); + if (s != NULL) { + source_file = s->as_C_string(); + } + } + } + if (k() != this_cp->pool_holder()) { + // only print something if the classes are different + if (source_file != NULL) { + tty->print("RESOLVE %s %s %s:%d\n", + this_cp->pool_holder()->external_name(), + InstanceKlass::cast(k())->external_name(), source_file, line_number); + } else { + tty->print("RESOLVE %s %s\n", + this_cp->pool_holder()->external_name(), + InstanceKlass::cast(k())->external_name()); + } + } +} + Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) { + assert(THREAD->is_Java_thread(), "must be a Java thread"); + // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*. - // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and - // tag is not updated atomicly. - + // It is not safe to rely on the tag bit's here, since we don't have a lock, and + // the entry and tag is not updated atomicly. CPSlot entry = this_cp->slot_at(which); if (entry.is_resolved()) { assert(entry.get_klass()->is_klass(), "must be"); @@ -198,115 +219,51 @@ return entry.get_klass(); } - // Acquire lock on constant oop while doing update. After we get the lock, we check if another object - // already has updated the object - assert(THREAD->is_Java_thread(), "must be a Java thread"); - bool do_resolve = false; - bool in_error = false; - - // Create a handle for the mirror. This will preserve the resolved class - // until the loader_data is registered. - Handle mirror_handle; - - Symbol* name = NULL; - Handle loader; - { MonitorLockerEx ml(this_cp->lock()); - - if (this_cp->tag_at(which).is_unresolved_klass()) { - if (this_cp->tag_at(which).is_unresolved_klass_in_error()) { - in_error = true; - } else { - do_resolve = true; - name = this_cp->unresolved_klass_at(which); - loader = Handle(THREAD, this_cp->pool_holder()->class_loader()); - } - } - } // unlocking constantPool - - - // The original attempt to resolve this constant pool entry failed so find the - // class of the original error and throw another error of the same class (JVMS 5.4.3). - // If there is a detail message, pass that detail message to the error constructor. - // The JVMS does not strictly require us to duplicate the same detail message, - // or any internal exception fields such as cause or stacktrace. But since the - // detail message is often a class name or other literal string, we will repeat it if - // we can find it in the symbol table. - if (in_error) { + // This tag doesn't change back to unresolved class unless at a safepoint. + if (this_cp->tag_at(which).is_unresolved_klass_in_error()) { + // The original attempt to resolve this constant pool entry failed so find the + // class of the original error and throw another error of the same class + // (JVMS 5.4.3). + // If there is a detail message, pass that detail message to the error. + // The JVMS does not strictly require us to duplicate the same detail message, + // or any internal exception fields such as cause or stacktrace. But since the + // detail message is often a class name or other literal string, we will repeat it + // if we can find it in the symbol table. throw_resolution_error(this_cp, which, CHECK_0); + ShouldNotReachHere(); } - if (do_resolve) { - // this_cp must be unlocked during resolve_or_fail - oop protection_domain = this_cp->pool_holder()->protection_domain(); - Handle h_prot (THREAD, protection_domain); - Klass* kk = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD); - KlassHandle k; - if (!HAS_PENDING_EXCEPTION) { - k = KlassHandle(THREAD, kk); - // preserve the resolved klass. - mirror_handle = Handle(THREAD, kk->java_mirror()); - // Do access check for klasses - verify_constant_pool_resolve(this_cp, k, THREAD); - } - - // Failed to resolve class. We must record the errors so that subsequent attempts - // to resolve this constant pool entry fail with the same error (JVMS 5.4.3). - if (HAS_PENDING_EXCEPTION) { - MonitorLockerEx ml(this_cp->lock()); - - // some other thread has beaten us and has resolved the class. - if (this_cp->tag_at(which).is_klass()) { - CLEAR_PENDING_EXCEPTION; - entry = this_cp->resolved_klass_at(which); - return entry.get_klass(); - } + Handle mirror_handle; + Symbol* name = entry.get_symbol(); + Handle loader (THREAD, this_cp->pool_holder()->class_loader()); + Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain()); + Klass* kk = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD); + KlassHandle k (THREAD, kk); + if (!HAS_PENDING_EXCEPTION) { + // preserve the resolved klass from unloading + mirror_handle = Handle(THREAD, kk->java_mirror()); + // Do access check for klasses + verify_constant_pool_resolve(this_cp, k, THREAD); + } - // The tag could have changed to in-error before the lock but we have to - // handle that here for the class case. - save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0); - } + // Failed to resolve class. We must record the errors so that subsequent attempts + // to resolve this constant pool entry fail with the same error (JVMS 5.4.3). + if (HAS_PENDING_EXCEPTION) { + save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0); + } - if (TraceClassResolution && !k()->oop_is_array()) { - // skip resolving the constant pool so that this code get's - // called the next time some bytecodes refer to this class. - ResourceMark rm; - int line_number = -1; - const char * source_file = NULL; - if (JavaThread::current()->has_last_Java_frame()) { - // try to identify the method which called this function. - vframeStream vfst(JavaThread::current()); - if (!vfst.at_end()) { - line_number = vfst.method()->line_number_from_bci(vfst.bci()); - Symbol* s = vfst.method()->method_holder()->source_file_name(); - if (s != NULL) { - source_file = s->as_C_string(); - } - } - } - if (k() != this_cp->pool_holder()) { - // only print something if the classes are different - if (source_file != NULL) { - tty->print("RESOLVE %s %s %s:%d\n", - this_cp->pool_holder()->external_name(), - InstanceKlass::cast(k())->external_name(), source_file, line_number); - } else { - tty->print("RESOLVE %s %s\n", - this_cp->pool_holder()->external_name(), - InstanceKlass::cast(k())->external_name()); - } - } + // Make this class loader depend upon the class loader owning the class reference + ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data(); + this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM + + if (TraceClassResolution && !k->oop_is_array()) { + // skip resolving the constant pool so that this code gets + // called the next time some bytecodes refer to this class. + trace_class_resolution(this_cp, k); return k(); } else { - MonitorLockerEx ml(this_cp->lock()); - // Only updated constant pool - if it is resolved. - do_resolve = this_cp->tag_at(which).is_unresolved_klass(); - if (do_resolve) { - ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data(); - this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM this_cp->klass_at_put(which, k()); } - } - } entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); @@ -576,7 +533,7 @@ switch (tag.value()) { case JVM_CONSTANT_UnresolvedClass: // return the class name in the error message - message = this_cp->unresolved_klass_at(which); + message = this_cp->klass_name_at(which); break; case JVM_CONSTANT_MethodHandle: // return the method handle name in the error message @@ -606,7 +563,6 @@ // in the resolution error table, so that the same exception is thrown again. void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int which, constantTag tag, TRAPS) { - assert(this_cp->lock()->is_locked(), "constant pool lock should be held"); Symbol* error = PENDING_EXCEPTION->klass()->name(); int error_tag = tag.error_value(); @@ -620,7 +576,14 @@ } else if (this_cp->tag_at(which).value() != error_tag) { Symbol* message = exception_message(this_cp, which, tag, PENDING_EXCEPTION); SystemDictionary::add_resolution_error(this_cp, which, error, message); - this_cp->tag_at_put(which, error_tag); + // CAS in the tag. If a thread beat us to registering this error that's fine. + // If another thread resolved the reference, this is an error. The resolution + // must deterministically get an error. So why do we save this? + // We save this because jvmti can add classes to the bootclass path after this + // error, so it needs to get the same error if the error is first. + jbyte old_tag = Atomic::cmpxchg((jbyte)error_tag, + (jbyte*)this_cp->tag_addr_at(which), (jbyte)tag.value()); + assert(old_tag == error_tag || old_tag == tag.value(), "should not be resolved otherwise"); } else { // some other thread put this in error state throw_resolution_error(this_cp, which, CHECK); @@ -710,7 +673,6 @@ THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { - MonitorLockerEx ml(this_cp->lock()); // lock cpool to change tag. save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } break; @@ -727,7 +689,6 @@ Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); if (HAS_PENDING_EXCEPTION) { - MonitorLockerEx ml(this_cp->lock()); // lock cpool to change tag. save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } break; @@ -765,22 +726,17 @@ } if (cache_index >= 0) { - // Cache the oop here also. - Handle result_handle(THREAD, result_oop); - MonitorLockerEx ml(this_cp->lock()); // don't know if we really need this - oop result = this_cp->resolved_references()->obj_at(cache_index); - // Benign race condition: resolved_references may already be filled in while we were trying to lock. + // Benign race condition: resolved_references may already be filled in. // The important thing here is that all threads pick up the same result. // It doesn't matter which racing thread wins, as long as only one // result is used by all threads, and all future queries. - // That result may be either a resolved constant or a failure exception. - if (result == NULL) { - this_cp->resolved_references()->obj_at_put(cache_index, result_handle()); - return result_handle(); + oop old_result = this_cp->resolved_references()->atomic_compare_exchange_oop(cache_index, result_oop, NULL); + if (old_result == NULL) { + return result_oop; // was installed } else { // Return the winning thread's result. This can be different than - // result_handle() for MethodHandles. - return result; + // the result here for MethodHandles. + return old_result; } } else { return result_oop; @@ -853,9 +809,8 @@ } -// Iterate over symbols and decrement ones which are Symbol*s. -// This is done during GC so do not need to lock constantPool unless we -// have per-thread safepoints. +// Iterate over symbols and decrement ones which are Symbol*s +// This is done during GC. // Only decrement the UTF8 symbols. Unresolved classes and strings point to // these symbols but didn't increment the reference count. void ConstantPool::unreference_symbols() { @@ -987,8 +942,8 @@ case JVM_CONSTANT_UnresolvedClass: { - Symbol* k1 = unresolved_klass_at(index1); - Symbol* k2 = cp2->unresolved_klass_at(index2); + Symbol* k1 = klass_name_at(index1); + Symbol* k2 = cp2->klass_name_at(index2); if (k1 == k2) { return true; } @@ -1970,7 +1925,6 @@ break; case JVM_CONSTANT_UnresolvedClass : // fall-through case JVM_CONSTANT_UnresolvedClassInError: { - // unresolved_klass_at requires lock or safe world. CPSlot entry = slot_at(index); if (entry.is_resolved()) { entry.get_klass()->print_value_on(st); diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/oops/constantPool.hpp --- a/hotspot/src/share/vm/oops/constantPool.hpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/oops/constantPool.hpp Thu Jun 19 11:16:10 2014 -0400 @@ -112,12 +112,12 @@ int _version; } _saved; - Monitor* _lock; - void set_tags(Array* tags) { _tags = tags; } void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); } void release_tag_at_put(int which, jbyte t) { tags()->release_at_put(which, t); } + u1* tag_addr_at(int which) const { return tags()->adr_at(which); } + void set_operands(Array* operands) { _operands = operands; } int flags() const { return _flags; } @@ -362,14 +362,6 @@ return CPSlot((Klass*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_klass(); } - // This method should only be used with a cpool lock or during parsing or gc - Symbol* unresolved_klass_at(int which) { // Temporary until actual use - Symbol* s = CPSlot((Symbol*)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol(); - // check that the klass is still unresolved. - assert(tag_at(which).is_unresolved_klass(), "Corrupted constant pool"); - return s; - } - // RedefineClasses() API support: Symbol* klass_at_noresolve(int which) { return klass_name_at(which); } @@ -818,6 +810,8 @@ static Klass* klass_at_impl(constantPoolHandle this_cp, int which, TRAPS); static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS); + static void trace_class_resolution(constantPoolHandle this_cp, KlassHandle k); + // Resolve string constants (to prevent allocation during compilation) static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS); @@ -848,8 +842,6 @@ void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; } int resolved_reference_length() const { return _saved._resolved_reference_length; } - void set_lock(Monitor* lock) { _lock = lock; } - Monitor* lock() { return _lock; } // Decrease ref counts of symbols that are in the constant pool // when the holder class is unloaded diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/oops/cpCache.cpp --- a/hotspot/src/share/vm/oops/cpCache.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/oops/cpCache.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -286,7 +286,9 @@ // the lock, so that when the losing writer returns, he can use the linked // cache entry. - MonitorLockerEx ml(cpool->lock()); + // Use the lock from the metaspace for this, which cannot stop for safepoint. + Mutex* metaspace_lock = cpool->pool_holder()->class_loader_data()->metaspace_lock(); + MutexLockerEx ml(metaspace_lock, Mutex::_no_safepoint_check_flag); if (!is_f1_null()) { return; } diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/oops/objArrayOop.cpp --- a/hotspot/src/share/vm/oops/objArrayOop.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/oops/objArrayOop.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -27,6 +27,22 @@ #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +oop objArrayOopDesc::atomic_compare_exchange_oop(int index, oop exchange_value, + oop compare_value) { + volatile HeapWord* dest; + if (UseCompressedOops) { + dest = (HeapWord*)obj_at_addr(index); + } else { + dest = (HeapWord*)obj_at_addr(index); + } + oop res = oopDesc::atomic_compare_exchange_oop(exchange_value, dest, compare_value, true); + // update card mark if success + if (res == compare_value) { + update_barrier_set((void*)dest, exchange_value); + } + return res; +} + #define ObjArrayOop_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ int objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \ diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/oops/objArrayOop.hpp --- a/hotspot/src/share/vm/oops/objArrayOop.hpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/oops/objArrayOop.hpp Thu Jun 19 11:16:10 2014 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -95,6 +95,9 @@ oop_store(obj_at_addr(index), value); } } + + oop atomic_compare_exchange_oop(int index, oop exchange_value, oop compare_value); + // Sizing static int header_size() { return arrayOopDesc::header_size(T_OBJECT); } int object_size() { return object_size(length()); } diff -r c937c5e883c5 -r e3af4e02b0d5 hotspot/src/share/vm/prims/jvmtiEnv.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Jun 18 14:21:28 2014 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Jun 19 11:16:10 2014 -0400 @@ -258,9 +258,6 @@ // VM representation. We don't attach the reconstituted class // bytes to the InstanceKlass here because they have not been // validated and we're not at a safepoint. - constantPoolHandle constants(current_thread, ikh->constants()); - MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it - JvmtiClassFileReconstituter reconstituter(ikh); if (reconstituter.get_error() != JVMTI_ERROR_NONE) { return reconstituter.get_error(); @@ -2445,9 +2442,6 @@ } instanceKlassHandle ikh(thread, k_oop); - constantPoolHandle constants(thread, ikh->constants()); - MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it - JvmtiConstantPoolReconstituter reconstituter(ikh); if (reconstituter.get_error() != JVMTI_ERROR_NONE) { return reconstituter.get_error(); @@ -2467,6 +2461,7 @@ return reconstituter.get_error(); } + constantPoolHandle constants(thread, ikh->constants()); *constant_pool_count_ptr = constants->length(); *constant_pool_byte_count_ptr = cpool_size; *constant_pool_bytes_ptr = cpool_bytes;