# HG changeset patch # User coleenp # Date 1506434597 14400 # Node ID d8e417df346864d4ca76339de56b297b44e35cef # Parent 468f0664cb39863e7193d7ed10956403a71e0f47 8081323: ConstantPool::_resolved_references is missing in heap dump Summary: Add resolved_references and init_lock as hidden static field in class so root is found. Reviewed-by: hseigel, jiangli, sspitsyn diff -r 468f0664cb39 -r d8e417df3468 src/hotspot/share/classfile/vmSymbols.hpp --- a/src/hotspot/share/classfile/vmSymbols.hpp Tue Sep 26 06:53:35 2017 -0400 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Tue Sep 26 10:03:17 2017 -0400 @@ -461,6 +461,8 @@ template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ template(module_entry_name, "module_entry") \ + template(resolved_references_name, "") \ + template(init_lock_name, "") \ \ /* name symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \ diff -r 468f0664cb39 -r d8e417df3468 src/hotspot/share/oops/constantPool.cpp --- a/src/hotspot/share/oops/constantPool.cpp Tue Sep 26 06:53:35 2017 -0400 +++ b/src/hotspot/share/oops/constantPool.cpp Tue Sep 26 10:03:17 2017 -0400 @@ -135,6 +135,16 @@ return (objArrayOop)_cache->resolved_references(); } +// Called from outside constant pool resolution where a resolved_reference array +// may not be present. +objArrayOop ConstantPool::resolved_references_or_null() const { + if (_cache == NULL) { + return NULL; + } else { + return (objArrayOop)_cache->resolved_references(); + } +} + // Create resolved_references array and mapping array for original cp indexes // The ldc bytecode was rewritten to have the resolved reference array index so need a way // to map it back for resolving and some unlikely miscellaneous uses. diff -r 468f0664cb39 -r d8e417df3468 src/hotspot/share/oops/constantPool.hpp --- a/src/hotspot/share/oops/constantPool.hpp Tue Sep 26 06:53:35 2017 -0400 +++ b/src/hotspot/share/oops/constantPool.hpp Tue Sep 26 10:03:17 2017 -0400 @@ -226,6 +226,7 @@ // resolved strings, methodHandles and callsite objects from the constant pool objArrayOop resolved_references() const; + objArrayOop resolved_references_or_null() const; // mapping resolved object array indexes to cp indexes and back. int object_to_cp_index(int index) { return reference_map()->at(index); } int cp_to_object_index(int index); diff -r 468f0664cb39 -r d8e417df3468 src/hotspot/share/services/heapDumper.cpp --- a/src/hotspot/share/services/heapDumper.cpp Tue Sep 26 06:53:35 2017 -0400 +++ b/src/hotspot/share/services/heapDumper.cpp Tue Sep 26 10:03:17 2017 -0400 @@ -856,6 +856,29 @@ if (fldc.access_flags().is_static()) field_count++; } + // Add in resolved_references which is referenced by the cpCache + // The resolved_references is an array per InstanceKlass holding the + // strings and other oops resolved from the constant pool. + oop resolved_references = ik->constants()->resolved_references_or_null(); + if (resolved_references != NULL) { + field_count++; + + // Add in the resolved_references of the used previous versions of the class + // in the case of RedefineClasses + InstanceKlass* prev = ik->previous_versions(); + while (prev != NULL && prev->constants()->resolved_references_or_null() != NULL) { + field_count++; + prev = prev->previous_versions(); + } + } + + // Also provide a pointer to the init_lock if present, so there aren't unreferenced int[0] + // arrays. + oop init_lock = ik->init_lock(); + if (init_lock != NULL) { + field_count++; + } + writer->write_u2(field_count); // pass 2 - dump the field descriptors and raw values @@ -873,6 +896,29 @@ dump_field_value(writer, sig->byte_at(0), addr); } } + + // Add resolved_references for each class that has them + if (resolved_references != NULL) { + writer->write_symbolID(vmSymbols::resolved_references_name()); // name + writer->write_u1(sig2tag(vmSymbols::object_array_signature())); // type + writer->write_objectID(resolved_references); + + // Also write any previous versions + InstanceKlass* prev = ik->previous_versions(); + while (prev != NULL && prev->constants()->resolved_references_or_null() != NULL) { + writer->write_symbolID(vmSymbols::resolved_references_name()); // name + writer->write_u1(sig2tag(vmSymbols::object_array_signature())); // type + writer->write_objectID(prev->constants()->resolved_references()); + prev = prev->previous_versions(); + } + } + + // Add init lock to the end if the class is not yet initialized + if (init_lock != NULL) { + writer->write_symbolID(vmSymbols::init_lock_name()); // name + writer->write_u1(sig2tag(vmSymbols::int_array_signature())); // type + writer->write_objectID(init_lock); + } } // dump the raw values of the instance fields of the given object @@ -908,7 +954,7 @@ if (!fld.access_flags().is_static()) { Symbol* sig = fld.signature(); - writer->write_symbolID(fld.name()); // name + writer->write_symbolID(fld.name()); // name writer->write_u1(sig2tag(sig)); // type } } @@ -1822,6 +1868,8 @@ // HPROF_GC_ROOT_JNI_GLOBAL JNIGlobalsDumper jni_dumper(writer()); JNIHandles::oops_do(&jni_dumper); + Universe::oops_do(&jni_dumper); // technically not jni roots, but global roots + // for things like preallocated throwable backtraces check_segment_length(); // HPROF_GC_ROOT_STICKY_CLASS