From 19437153efc9f428c1d13bf5934ad726056c09aa Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 10 Dec 2025 12:21:01 -0500 Subject: [PATCH 1/2] 8373442: [lworld] Fix CDS heap dumping crashes --- src/hotspot/share/cds/aotMapLogger.cpp | 55 ++++++++++++++----- src/hotspot/share/cds/aotMapLogger.hpp | 3 +- src/hotspot/share/cds/aotMappedHeapWriter.cpp | 6 +- .../share/cds/aotStreamedHeapWriter.cpp | 4 +- src/hotspot/share/oops/flatArrayKlass.cpp | 33 ++++++----- src/hotspot/share/oops/flatArrayKlass.hpp | 1 + src/hotspot/share/oops/objArrayOop.hpp | 1 - src/hotspot/share/oops/refArrayOop.hpp | 1 + 8 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp index d0a63c56093..18fa8521581 100644 --- a/src/hotspot/share/cds/aotMapLogger.cpp +++ b/src/hotspot/share/cds/aotMapLogger.cpp @@ -492,7 +492,7 @@ void AOTMapLogger::log_as_hex(address base, address top, address requested_base, } #if INCLUDE_CDS_JAVA_HEAP -// FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse +// FakeOop (and subclasses FakeMirror, FakeString, FakeRefArray, FakeFlatArray, FakeTypeArray) are used to traverse // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops: // - They do not reside inside the range of the heap. // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*) @@ -530,7 +530,8 @@ class AOTMapLogger::FakeOop { FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {} FakeMirror as_mirror(); - FakeObjArray as_obj_array(); + FakeRefArray as_ref_array(); + FakeFlatArray as_flat_array(); FakeString as_string(); FakeTypeArray as_type_array(); @@ -618,25 +619,42 @@ class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop { } }; // AOTMapLogger::FakeMirror -class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop { - objArrayOop raw_objArrayOop() { - return (objArrayOop)raw_oop(); +class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop { + refArrayOop raw_refArrayOop() { + return (refArrayOop)raw_oop(); } public: - FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} + FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} int length() { - return raw_objArrayOop()->length(); + return raw_refArrayOop()->length(); } FakeOop obj_at(int i) { if (UseCompressedOops) { - return read_oop_at(raw_objArrayOop()->obj_at_addr(i)); + return read_oop_at(raw_refArrayOop()->obj_at_addr(i)); } else { - return read_oop_at(raw_objArrayOop()->obj_at_addr(i)); + return read_oop_at(raw_refArrayOop()->obj_at_addr(i)); } } -}; // AOTMapLogger::FakeObjArray +}; // AOTMapLogger::FakeRefArray + +class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop { + flatArrayOop raw_flatArrayOop() { + return (flatArrayOop)raw_oop(); + } + +public: + FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} + + int length() { + return raw_flatArrayOop()->length(); + } + void print_elements_on(outputStream* st) { + FlatArrayKlass::cast(real_klass())->oop_print_elements_on(raw_flatArrayOop(), st); + } + +}; // AOTMapLogger::FakeRefArray class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop { public: @@ -676,9 +694,14 @@ AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() { return FakeMirror(_iter, _data); } -AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() { - precond(real_klass()->is_objArray_klass()); - return FakeObjArray(_iter, _data); +AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() { + precond(real_klass()->is_refArray_klass()); + return FakeRefArray(_iter, _data); +} + +AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() { + precond(real_klass()->is_flatArray_klass()); + return FakeFlatArray(_iter, _data); } AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() { @@ -923,8 +946,10 @@ void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) { if (real_klass->is_typeArray_klass()) { fake_oop.as_type_array().print_elements_on(st); - } else if (real_klass->is_objArray_klass()) { - FakeObjArray fake_obj_array = fake_oop.as_obj_array(); + } else if (real_klass->is_flatArray_klass()) { + fake_oop.as_flat_array().print_elements_on(st); + } else if (real_klass->is_refArray_klass()) { + FakeRefArray fake_obj_array = fake_oop.as_ref_array(); bool is_logging_root_segment = fake_oop.is_root_segment(); for (int i = 0; i < fake_obj_array.length(); i++) { diff --git a/src/hotspot/share/cds/aotMapLogger.hpp b/src/hotspot/share/cds/aotMapLogger.hpp index ba188514861..a6bbd7ae392 100644 --- a/src/hotspot/share/cds/aotMapLogger.hpp +++ b/src/hotspot/share/cds/aotMapLogger.hpp @@ -69,7 +69,8 @@ class AOTMapLogger : AllStatic { // FakeOop and subtypes class FakeOop; class FakeMirror; - class FakeObjArray; + class FakeRefArray; + class FakeFlatArray; class FakeString; class FakeTypeArray; diff --git a/src/hotspot/share/cds/aotMappedHeapWriter.cpp b/src/hotspot/share/cds/aotMappedHeapWriter.cpp index e01a078f44c..514b1acc1c9 100644 --- a/src/hotspot/share/cds/aotMappedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotMappedHeapWriter.cpp @@ -436,6 +436,7 @@ HeapWord* AOTMappedHeapWriter::init_filler_array_at_buffer_top(int array_length, if (UseCompactObjectHeaders) { oopDesc::release_set_mark(mem, markWord::prototype().set_narrow_klass(nk)); } else { + assert(!EnableValhalla || Universe::objectArrayKlass()->prototype_header() == markWord::prototype(), "should be the same"); oopDesc::set_mark(mem, markWord::prototype()); cast_to_oop(mem)->set_narrow_klass(nk); } @@ -642,7 +643,8 @@ void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop oop fake_oop = cast_to_oop(buffered_addr); if (UseCompactObjectHeaders) { - fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk)); + markWord prototype_header = src_klass->prototype_header().set_narrow_klass(nk); + fake_oop->set_mark(prototype_header); } else { fake_oop->set_narrow_klass(nk); } @@ -655,7 +657,7 @@ void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop if (!src_obj->fast_no_hash_check() && (!(EnableValhalla && src_obj->mark().is_inline_type()))) { intptr_t src_hash = src_obj->identity_hash(); if (UseCompactObjectHeaders) { - fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash)); + fake_oop->set_mark(fake_oop->mark().copy_set_hash(src_hash)); } else if (EnableValhalla) { fake_oop->set_mark(src_klass->prototype_header().copy_set_hash(src_hash)); } else { diff --git a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp index 16acebc7d8d..9e329d8e11e 100644 --- a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp @@ -390,14 +390,14 @@ void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_add assert(UseCompressedClassPointers, "Archived heap only supported for compressed klasses"); narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); - markWord mw = markWord::prototype(); + markWord mw = Arguments::enable_preview() ? src_klass->prototype_header() : markWord::prototype(); oopDesc* fake_oop = (oopDesc*)buffered_addr; // We need to retain the identity_hash, because it may have been used by some hashtables // in the shared heap. This also has the side effect of pre-initializing the // identity_hash for all shared objects, so they are less likely to be written // into during run time, increasing the potential of memory sharing. - if (src_obj != nullptr) { + if (src_obj != nullptr && !src_klass->is_inline_klass()) { intptr_t src_hash = src_obj->identity_hash(); mw = mw.copy_set_hash(src_hash); } diff --git a/src/hotspot/share/oops/flatArrayKlass.cpp b/src/hotspot/share/oops/flatArrayKlass.cpp index aef3db27caa..e348e7ec7bc 100644 --- a/src/hotspot/share/oops/flatArrayKlass.cpp +++ b/src/hotspot/share/oops/flatArrayKlass.cpp @@ -403,25 +403,11 @@ void FlatArrayKlass::print_value_on(outputStream* st) const { st->print("[]"); } - #ifndef PRODUCT void FlatArrayKlass::oop_print_on(oop obj, outputStream* st) { ArrayKlass::oop_print_on(obj, st); flatArrayOop va = flatArrayOop(obj); - InlineKlass* vk = element_klass(); - int print_len = MIN2(va->length(), MaxElementPrintSize); - for(int index = 0; index < print_len; index++) { - int off = (address) va->value_at_addr(index, layout_helper()) - cast_from_oop
(obj); - st->print_cr(" - Index %3d offset %3d: ", index, off); - oop obj = cast_to_oop((address)va->value_at_addr(index, layout_helper()) - vk->payload_offset()); - FieldPrinter print_field(st, obj); - vk->do_nonstatic_fields(&print_field); - st->cr(); - } - int remaining = va->length() - print_len; - if (remaining > 0) { - st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); - } + oop_print_elements_on(va, st); } #endif //PRODUCT @@ -445,6 +431,23 @@ void FlatArrayKlass::oop_print_value_on(oop obj, outputStream* st) { } } +void FlatArrayKlass::oop_print_elements_on(flatArrayOop fa, outputStream* st) { + InlineKlass* vk = element_klass(); + int print_len = MIN2(fa->length(), MaxElementPrintSize); + for(int index = 0; index < print_len; index++) { + int off = (address) fa->value_at_addr(index, layout_helper()) - cast_from_oop
(fa); + st->print_cr(" - Index %3d offset %3d: ", index, off); + oop obj = cast_to_oop((address)fa->value_at_addr(index, layout_helper()) - vk->payload_offset()); + FieldPrinter print_field(st, obj); + vk->do_nonstatic_fields(&print_field); + st->cr(); + } + int remaining = fa->length() - print_len; + if (remaining > 0) { + st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); + } +} + // Verification class VerifyElementClosure: public BasicOopIterateClosure { public: diff --git a/src/hotspot/share/oops/flatArrayKlass.hpp b/src/hotspot/share/oops/flatArrayKlass.hpp index 1292445cbd3..39295ce2a9d 100644 --- a/src/hotspot/share/oops/flatArrayKlass.hpp +++ b/src/hotspot/share/oops/flatArrayKlass.hpp @@ -145,6 +145,7 @@ class FlatArrayKlass : public ObjArrayKlass { #ifndef PRODUCT void oop_print_on(oop obj, outputStream* st); #endif + void oop_print_elements_on(flatArrayOop fa, outputStream* st); // Verification void verify_on(outputStream* st); diff --git a/src/hotspot/share/oops/objArrayOop.hpp b/src/hotspot/share/oops/objArrayOop.hpp index ad06eb759d4..0a617cadd4a 100644 --- a/src/hotspot/share/oops/objArrayOop.hpp +++ b/src/hotspot/share/oops/objArrayOop.hpp @@ -43,7 +43,6 @@ class objArrayOopDesc : public arrayOopDesc { friend class Continuation; template friend class RawOopWriter; - friend class AOTMapLogger; template T* obj_at_addr(int index) const; diff --git a/src/hotspot/share/oops/refArrayOop.hpp b/src/hotspot/share/oops/refArrayOop.hpp index f48cd3d47c8..ecdb92ebec7 100644 --- a/src/hotspot/share/oops/refArrayOop.hpp +++ b/src/hotspot/share/oops/refArrayOop.hpp @@ -44,6 +44,7 @@ class refArrayOopDesc : public arrayOopDesc { friend class Continuation; template friend class RawOopWriter; + friend class AOTMapLogger; template T* obj_at_addr(int index) const; From c01ef0a24eabd87f1f9c3794e26f277a603f12d5 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 11 Dec 2025 14:57:58 -0500 Subject: [PATCH 2/2] Add comment that archiving flattened arrays with oops in the inline class element type is not supported. --- src/hotspot/share/cds/aotMapLogger.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp index 18fa8521581..712d39a978a 100644 --- a/src/hotspot/share/cds/aotMapLogger.cpp +++ b/src/hotspot/share/cds/aotMapLogger.cpp @@ -947,6 +947,8 @@ void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) { if (real_klass->is_typeArray_klass()) { fake_oop.as_type_array().print_elements_on(st); } else if (real_klass->is_flatArray_klass()) { + // Archiving FlatArrayOop with embedded oops is not supported. + // TODO: add restriction. fake_oop.as_flat_array().print_elements_on(st); } else if (real_klass->is_refArray_klass()) { FakeRefArray fake_obj_array = fake_oop.as_ref_array();