From 167acd13278bc745dd15a465a46604fa858d57a6 Mon Sep 17 00:00:00 2001 From: fmatte Date: Wed, 4 Jul 2018 03:02:43 -0400 Subject: [PATCH] 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: dholmes, coleenp --- src/share/vm/classfile/vmSymbols.hpp | 2 ++ src/share/vm/oops/constantPool.cpp | 12 ++++++- src/share/vm/oops/constantPool.hpp | 3 +- src/share/vm/services/heapDumper.cpp | 51 ++++++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp index 90ffcf9e7..1de221359 100644 --- a/src/share/vm/classfile/vmSymbols.hpp +++ b/src/share/vm/classfile/vmSymbols.hpp @@ -418,6 +418,7 @@ template(getProtectionDomain_name, "getProtectionDomain") \ template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ + template(resolved_references_name, "") \ template(referencequeue_null_name, "NULL") \ template(referencequeue_enqueued_name, "ENQUEUED") \ \ @@ -508,6 +509,7 @@ template(class_array_signature, "[Ljava/lang/Class;") \ template(classloader_signature, "Ljava/lang/ClassLoader;") \ template(object_signature, "Ljava/lang/Object;") \ + template(object_array_signature, "[Ljava/lang/Object;") \ template(class_signature, "Ljava/lang/Class;") \ template(string_signature, "Ljava/lang/String;") \ template(reference_signature, "Ljava/lang/ref/Reference;") \ diff --git a/src/share/vm/oops/constantPool.cpp b/src/share/vm/oops/constantPool.cpp index b76435fe9..7a4d50061 100644 --- a/src/share/vm/oops/constantPool.cpp +++ b/src/share/vm/oops/constantPool.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -109,6 +109,16 @@ objArrayOop ConstantPool::resolved_references() const { return (objArrayOop)JNIHandles::resolve(_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)JNIHandles::resolve(_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 --git a/src/share/vm/oops/constantPool.hpp b/src/share/vm/oops/constantPool.hpp index f170decc4..0698eb40e 100644 --- a/src/share/vm/oops/constantPool.hpp +++ b/src/share/vm/oops/constantPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -200,6 +200,7 @@ class ConstantPool : public Metadata { // 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 --git a/src/share/vm/services/heapDumper.cpp b/src/share/vm/services/heapDumper.cpp index 9086cfb84..a62ce9114 100644 --- a/src/share/vm/services/heapDumper.cpp +++ b/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, 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 @@ -815,6 +815,28 @@ void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { 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 = ikh->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 = ikh->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 = ikh->init_lock(); + if (init_lock != NULL) { + field_count++; + } writer->write_u2(field_count); @@ -833,6 +855,29 @@ void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { 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 = ikh->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 @@ -868,7 +913,7 @@ void DumperSupport::dump_instance_field_descriptors(DumpWriter* writer, Klass* k 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 } } @@ -1758,6 +1803,8 @@ void VM_HeapDumper::doit() { // 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 -- GitLab