changeset 8870:ad057f2e3211

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
author fmatte
date Wed, 04 Jul 2018 03:02:43 -0400
parents 5792d995ed26
children ad33c4bbce66 5ba59d58d976 e25662a88116
files src/share/vm/classfile/vmSymbols.hpp src/share/vm/oops/constantPool.cpp src/share/vm/oops/constantPool.hpp src/share/vm/services/heapDumper.cpp
diffstat 4 files changed, 64 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Jun 27 03:04:33 2018 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 04 03:02:43 2018 -0400
@@ -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,                  "<resolved_references>")                    \
   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;")                                \
--- a/src/share/vm/oops/constantPool.cpp	Wed Jun 27 03:04:33 2018 -0700
+++ b/src/share/vm/oops/constantPool.cpp	Wed Jul 04 03:02:43 2018 -0400
@@ -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 @@
   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.
--- a/src/share/vm/oops/constantPool.hpp	Wed Jun 27 03:04:33 2018 -0700
+++ b/src/share/vm/oops/constantPool.hpp	Wed Jul 04 03:02:43 2018 -0400
@@ -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 @@
 
   // 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);
--- a/src/share/vm/services/heapDumper.cpp	Wed Jun 27 03:04:33 2018 -0700
+++ b/src/share/vm/services/heapDumper.cpp	Wed Jul 04 03:02:43 2018 -0400
@@ -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 @@
   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 @@
       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 @@
     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 @@
   // 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