From f51363e0277210d2b2f6cdb4d2bf6c732a02c76a Mon Sep 17 00:00:00 2001 From: Ioi Lam <iklam@openjdk.org> Date: Thu, 28 Nov 2024 01:15:15 +0000 Subject: [PATCH] 8344913: Improve -Xlog:cds+map+oop logging for Java mirrors Reviewed-by: dholmes, ccheung --- src/hotspot/share/cds/archiveBuilder.cpp | 96 ++++++++++++++++--- .../jtreg/runtime/cds/CDSMapReader.java | 6 +- 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 36a17813d32..1cd9d13c3ba 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -1294,10 +1294,15 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { if (source_oop != nullptr) { // This is a regular oop that got archived. - print_oop_with_requested_addr_cr(&st, source_oop, false); + // Don't print the requested addr again as we have just printed it at the beginning of the line. + // Example: + // 0x00000007ffd27938: @@ Object (0xfffa4f27) java.util.HashMap + print_oop_info_cr(&st, source_oop, /*print_requested_addr=*/false); byte_size = source_oop->size() * BytesPerWord; } else if ((byte_size = ArchiveHeapWriter::get_filler_size_at(start)) > 0) { // We have a filler oop, which also does not exist in BufferOffsetToSourceObjectTable. + // Example: + // 0x00000007ffc3ffd8: @@ Object filler 40 bytes st.print_cr("filler " SIZE_FORMAT " bytes", byte_size); } else { ShouldNotReachHere(); @@ -1315,7 +1320,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { // ArchivedFieldPrinter is used to print the fields of archived objects. We can't // use _source_obj->print_on(), because we want to print the oop fields - // in _source_obj with their requested addresses using print_oop_with_requested_addr_cr(). + // in _source_obj with their requested addresses using print_oop_info_cr(). class ArchivedFieldPrinter : public FieldClosure { ArchiveHeapInfo* _heap_info; outputStream* _st; @@ -1331,8 +1336,14 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { switch (ft) { case T_ARRAY: case T_OBJECT: - fd->print_on(_st); // print just the name and offset - print_oop_with_requested_addr_cr(_st, _source_obj->obj_field(fd->offset())); + { + fd->print_on(_st); // print just the name and offset + oop obj = _source_obj->obj_field(fd->offset()); + if (java_lang_Class::is_instance(obj)) { + obj = HeapShared::scratch_java_mirror(obj); + } + print_oop_info_cr(_st, obj); + } break; default: if (ArchiveHeapWriter::is_marked_as_native_pointer(_heap_info, _source_obj, fd->offset())) { @@ -1388,37 +1399,78 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { objArrayOop source_obj_array = objArrayOop(source_oop); for (int i = 0; i < source_obj_array->length(); i++) { st.print(" -%4d: ", i); - print_oop_with_requested_addr_cr(&st, source_obj_array->obj_at(i)); + oop obj = source_obj_array->obj_at(i); + if (java_lang_Class::is_instance(obj)) { + obj = HeapShared::scratch_java_mirror(obj); + } + print_oop_info_cr(&st, obj); } } else { st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size()); ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr); InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field); + + if (java_lang_Class::is_instance(source_oop)) { + oop scratch_mirror = source_oop; + st.print(" - signature: "); + print_class_signature_for_mirror(&st, scratch_mirror); + st.cr(); + + Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror); + if (src_klass != nullptr && src_klass->is_instance_klass()) { + oop rr = HeapShared::scratch_resolved_references(InstanceKlass::cast(src_klass)->constants()); + st.print(" - archived_resolved_references: "); + print_oop_info_cr(&st, rr); + + // We need to print the fields in the scratch_mirror, not the original mirror. + // (if a class is not aot-initialized, static fields in its scratch mirror will be cleared). + assert(scratch_mirror == HeapShared::scratch_java_mirror(src_klass->java_mirror()), "sanity"); + st.print_cr("- ---- static fields (%d):", java_lang_Class::static_oop_field_count(scratch_mirror)); + InstanceKlass::cast(src_klass)->do_local_static_fields(&print_field); + } + } } } } + static void print_class_signature_for_mirror(outputStream* st, oop scratch_mirror) { + assert(java_lang_Class::is_instance(scratch_mirror), "sanity"); + if (java_lang_Class::is_primitive(scratch_mirror)) { + for (int i = T_BOOLEAN; i < T_VOID+1; i++) { + BasicType bt = (BasicType)i; + if (!is_reference_type(bt) && scratch_mirror == HeapShared::scratch_java_mirror(bt)) { + oop orig_mirror = Universe::java_mirror(bt); + java_lang_Class::print_signature(orig_mirror, st); + return; + } + } + ShouldNotReachHere(); + } + java_lang_Class::print_signature(scratch_mirror, st); + } + static void log_heap_roots() { LogStreamHandle(Trace, cds, map, oops) st; if (st.is_enabled()) { for (int i = 0; i < HeapShared::pending_roots()->length(); i++) { st.print("roots[%4d]: ", i); - print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i)); + print_oop_info_cr(&st, HeapShared::pending_roots()->at(i)); } } } - // The output looks like this. The first number is the requested address. The second number is - // the narrowOop version of the requested address. - // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class + // Example output: + // - The first number is the requested address (if print_requested_addr == true) + // - The second number is the narrowOop version of the requested address (if UseCompressedOops == true) + // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class Ljava/util/Array; // 0x00000007ffc000f8 (0xfff8001f) [B length: 11 - static void print_oop_with_requested_addr_cr(outputStream* st, oop source_oop, bool print_addr = true) { + static void print_oop_info_cr(outputStream* st, oop source_oop, bool print_requested_addr = true) { if (source_oop == nullptr) { st->print_cr("null"); } else { ResourceMark rm; oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop); - if (print_addr) { + if (print_requested_addr) { st->print(PTR_FORMAT " ", p2i(requested_obj)); } if (UseCompressedOops) { @@ -1428,7 +1480,27 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { int array_len = arrayOop(source_oop)->length(); st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len); } else { - st->print_cr("%s", source_oop->klass()->external_name()); + st->print("%s", source_oop->klass()->external_name()); + + if (java_lang_String::is_instance(source_oop)) { + st->print(" "); + java_lang_String::print(source_oop, st); + } else if (java_lang_Class::is_instance(source_oop)) { + oop scratch_mirror = source_oop; + + st->print(" "); + print_class_signature_for_mirror(st, scratch_mirror); + + Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror); + if (src_klass != nullptr && src_klass->is_instance_klass()) { + InstanceKlass* buffered_klass = + ArchiveBuilder::current()->get_buffered_addr(InstanceKlass::cast(src_klass)); + if (buffered_klass->has_aot_initialized_mirror()) { + st->print(" (aot-inited)"); + } + } + } + st->cr(); } } } diff --git a/test/hotspot/jtreg/runtime/cds/CDSMapReader.java b/test/hotspot/jtreg/runtime/cds/CDSMapReader.java index 98532163136..f9fc4c222cb 100644 --- a/test/hotspot/jtreg/runtime/cds/CDSMapReader.java +++ b/test/hotspot/jtreg/runtime/cds/CDSMapReader.java @@ -38,7 +38,7 @@ This is a simple parser for parsing the output of The map file contains patterns like this for the heap objects: ====================================================================== -0x00000000ffe00000: @@ Object (0xffe00000) java.lang.String +0x00000000ffe00000: @@ Object (0xffe00000) java.lang.String "" - klass: 'java/lang/String' 0x0000000800010220 - fields (3 words): - private 'hash' 'I' @12 0 (0x00000000) @@ -149,11 +149,11 @@ public class CDSMapReader { // (one address) // 0x00000007ffc00000: @@ Object java.lang.String - static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object (.*)"); + static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object ([^ ]*)"); // (two addresses) // 0x00000007ffc00000: @@ Object (0xfff80000) java.lang.String - static Pattern objPattern2 = Pattern.compile("^0x([0-9a-f]+): @@ Object [(]0x([0-9a-f]+)[)] (.*)"); + static Pattern objPattern2 = Pattern.compile("^0x([0-9a-f]+): @@ Object [(]0x([0-9a-f]+)[)] ([^ ]*)"); // - klass: 'java/lang/String' 0x0000000800010290 static Pattern instanceObjKlassPattern = Pattern.compile("^ - klass: '([^']+)' 0x([0-9a-f]+)");