Crash in ArchiveHeapWriter::compute_ptrmap when archiving heap objects of excluded classes
ioi.lam at oracle.com
ioi.lam at oracle.com
Tue Feb 10 01:02:36 UTC 2026
Hi Anton,
Thanks for the bug report. I have created
https://bugs.openjdk.org/browse/JDK-8377512
(I am not sure if you have permission to edit the bug, but I think some
of your colleagues at Azul should have permission).
Do you have more information, such as an hs_err file?
My guess is we have a ResolvedMethodName object that points to a method
of an excluded class
void HeapShared::mark_native_pointers(oop orig_obj) {
if (java_lang_Class::is_instance(orig_obj)) {
ArchiveHeapWriter::mark_native_pointer(orig_obj,
java_lang_Class::klass_offset());
ArchiveHeapWriter::mark_native_pointer(orig_obj,
java_lang_Class::array_klass_offset());
} else if (java_lang_invoke_ResolvedMethodName::is_instance(orig_obj)) {
ArchiveHeapWriter::mark_native_pointer(orig_obj,
java_lang_invoke_ResolvedMethodName::vmtarget_offset());
}
}
However, we should exclude all resolved lambda sites that reference an
excluded class. As a result, we should never archive such
a ResolvedMethodName:
0 AOTConstantPoolResolver::check_methodtype_signature
1 AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg
2 AOTConstantPoolResolver::is_indy_resolution_deterministic
3 AOTConstantPoolResolver::is_resolution_deterministic
4 ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic
5 ConstantPoolCache::remove_unshareable_info
6 ConstantPool::remove_unshareable_entries
7 ConstantPool::remove_unshareable_info
8 ArchiveBuilder::make_klasses_shareable
9 VM_PopulateDumpSharedSpace::doit
10 VM_Operation::evaluate
We have test cases in here:
LambdaContainsOldInf.java: output.shouldMatch("Cannot aot-resolve Lambda
proxy because OldProvider is excluded");
resolvedConstants/ResolvedConstants.java: .shouldContain("Cannot
aot-resolve Lambda proxy of interface type InterfaceWithClinit")
resolvedConstants/AOTLinkedLambdas.java: dumpOut.shouldContain("Can
aot-resolve Lambda proxy of interface type IA");
If you can find a way to reproduce the problem it would be great. You
can find more information about the failure with this:
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp
b/src/hotspot/share/cds/archiveHeapWriter.cpp
index ee1e334e84b..7f68e648431 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -754,6 +754,14 @@ void
ArchiveHeapWriter::compute_ptrmap(ArchiveHeapInfo* heap_info) {
Metadata** buffered_field_addr =
requested_addr_to_buffered_addr(requested_field_addr);
Metadata* native_ptr = *buffered_field_addr;
guarantee(native_ptr != nullptr, "sanity");
+ if
(!ArchiveBuilder::current()->has_been_buffered((address)native_ptr)) {
+ ResourceMark rm;
+ tty->print_cr("Marking native pointer for oop %p (type = %s,
offset = %d)",
+ cast_from_oop<void*>(src_obj),
src_obj->klass()->external_name(), field_offset);
+ src_obj->print_on(tty);
+ tty->cr();
+ }
+
Thanks
- Ioi
On 2/9/26 7:24 AM, Anton Voznia wrote:
>
> Hi all,
>
>
> I have a question about a potential bug in AOT heap archiving.
>
>
> We observe a crash (guarantee failure) while creating the AOT cache
> with JDK 25, at:
>
> _https://github.com/openjdk/jdk25u-dev/blob/40ec273de548b47fc08d02bbe7c1cb3b48ebad17/src/hotspot/share/cds/archiveHeapWriter.cpp#L757_
>
>
> The failure happens because:
>
> get_buffered_addr(src_addr) == nullptr
>
>
> What means that a native pointer is present in _native_pointers but
> there is no corresponding buffered address, even though the
> SourceObjInfo was successfully added to _src_obj_table.
>
> The failing check is:
>
> guarantee(ArchiveBuilder::current()->has_been_buffered((address)native_ptr),
>
> "Metadata %p should have been archived", native_ptr);
>
>
> further investigation showed that we collect pointers into
> _native_pointers without checking whether the corresponding class was
> excluded (via class exclusion or link-time verification failures):
>
> _https://github.com/openjdk/jdk25u-dev/blob/40ec273de548b47fc08d02bbe7c1cb3b48ebad17/src/hotspot/share/cds/heapShared.cpp#L308_
>
>
> However, the SourceObjInfo::_buffered_addr seems to be assigned only
> for objects that are actually copied (i.e., not excluded).
>
>
> In particular, this SourceObjInfo didn’t end up in _ro_src_objs or
> _rw_src_objs because it didn’t satisfy the following condition:
>
> _https://github.com/openjdk/jdk25u-dev/blob/40ec273de548b47fc08d02bbe7c1cb3b48ebad17/src/hotspot/share/cds/archiveBuilder.cpp#L467_
>
>
> if (created && src_info.should_copy()) {
>
> if (read_only) {
>
> _ro_src_objs.append(p);
>
> } else {
>
> _rw_src_objs.append(p);
>
> }
>
> return true; // Need to recurse into this ref only if we are copying it
>
> }
>
>
> created is true (object exists in _src_obj_table), but
> src_info.should_copy() is false because _follow_mode is set_to_null
> (not make_a_copy).
>
>
> So it looks like we may end up with an item in _native_pointers for
> which we will never assign a buffered address.
>
> However, later we expect every item in _native_pointers to have one
> buffered address.
>
>
> Is this logic correct, or am I missing a step that guarantees
> buffering for all _native_pointers items?
>
> It seems, we have to check for a class exclusion before adding into
> _native_pointers.
>
>
> Unfortunately, I wasn’t able to reproduce the issue locally.
>
>
> Thanks and best regards,
> Anton Voznia
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/leyden-dev/attachments/20260209/2a1d7fff/attachment.htm>
More information about the leyden-dev
mailing list