Crash in ArchiveHeapWriter::compute_ptrmap when archiving heap objects of excluded classes

XMLWordPrintable

      Reported in https://mail.openjdk.org/pipermail/leyden-dev/2026-February/002930.html

      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.

            Assignee:
            Ioi Lam
            Reporter:
            Ioi Lam
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: