8377777: Improve logging when rejecting assets from the AOT archive

Reviewed-by: adinn, iklam, stuefe
This commit is contained in:
María Arias de Reyna Domínguez 2026-03-02 16:16:31 +00:00 committed by Andrew Dinn
parent 7b5b70c9cb
commit 4fbc29199c
4 changed files with 42 additions and 20 deletions

View File

@ -310,8 +310,9 @@ void ConstantPool::iterate_archivable_resolved_references(Function function) {
if (method_entries != nullptr) {
for (int i = 0; i < method_entries->length(); i++) {
ResolvedMethodEntry* rme = method_entries->adr_at(i);
const char* rejection_reason = nullptr;
if (rme->is_resolved(Bytecodes::_invokehandle) && rme->has_appendix() &&
cache()->can_archive_resolved_method(this, rme)) {
cache()->can_archive_resolved_method(this, rme, rejection_reason)) {
int rr_index = rme->resolved_references_index();
assert(resolved_reference_at(rr_index) != nullptr, "must exist");
function(rr_index);

View File

@ -450,12 +450,15 @@ void ConstantPoolCache::remove_resolved_field_entries_if_non_deterministic() {
Symbol* klass_name = cp->klass_name_at(klass_cp_index);
Symbol* name = cp->uncached_name_ref_at(cp_index);
Symbol* signature = cp->uncached_signature_ref_at(cp_index);
log.print("%s field CP entry [%3d]: %s => %s.%s:%s%s",
(archived ? "archived" : "reverted"),
cp_index,
cp->pool_holder()->name()->as_C_string(),
klass_name->as_C_string(), name->as_C_string(), signature->as_C_string(),
rfi->is_resolved(Bytecodes::_getstatic) || rfi->is_resolved(Bytecodes::_putstatic) ? " *** static" : "");
if (resolved) {
log.print("%s field CP entry [%3d]: %s => %s.%s:%s%s%s",
(archived ? "archived" : "reverted"),
cp_index,
cp->pool_holder()->name()->as_C_string(),
klass_name->as_C_string(), name->as_C_string(), signature->as_C_string(),
rfi->is_resolved(Bytecodes::_getstatic) || rfi->is_resolved(Bytecodes::_putstatic) ? " *** static" : "",
(archived ? "" : " (resolution is not deterministic)"));
}
}
ArchiveBuilder::alloc_stats()->record_field_cp_entry(archived, resolved && !archived);
}
@ -474,32 +477,40 @@ void ConstantPoolCache::remove_resolved_method_entries_if_non_deterministic() {
rme->is_resolved(Bytecodes::_invokehandle) ||
(rme->is_resolved(Bytecodes::_invokestatic) && VM_Version::supports_fast_class_init_checks());
const char* rejection_reason = nullptr;
if (resolved && !CDSConfig::is_dumping_preimage_static_archive()
&& can_archive_resolved_method(src_cp, rme)) {
&& can_archive_resolved_method(src_cp, rme, rejection_reason)) {
rme->mark_and_relocate(src_cp);
archived = true;
} else {
rme->remove_unshareable_info();
}
LogStreamHandle(Trace, aot, resolve) log;
if (log.is_enabled()) {
LogTarget(Trace, aot, resolve) lt;
if (lt.is_enabled()) {
ResourceMark rm;
int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index);
Symbol* klass_name = cp->klass_name_at(klass_cp_index);
Symbol* name = cp->uncached_name_ref_at(cp_index);
Symbol* signature = cp->uncached_signature_ref_at(cp_index);
log.print("%s%s method CP entry [%3d]: %s %s.%s:%s",
LogStream ls(lt);
if (resolved) {
ls.print("%s%s method CP entry [%3d]: %s %s.%s:%s",
(archived ? "archived" : "reverted"),
(rme->is_resolved(Bytecodes::_invokeinterface) ? " interface" : ""),
cp_index,
cp->pool_holder()->name()->as_C_string(),
klass_name->as_C_string(), name->as_C_string(), signature->as_C_string());
if (rejection_reason != nullptr) {
ls.print(" %s", rejection_reason);
}
}
if (archived) {
Klass* resolved_klass = cp->resolved_klass_at(klass_cp_index);
log.print(" => %s%s",
ls.print(" => %s%s",
resolved_klass->name()->as_C_string(),
(rme->is_resolved(Bytecodes::_invokestatic) ? " *** static" : ""));
}
ls.cr();
}
ArchiveBuilder::alloc_stats()->record_method_cp_entry(archived, resolved && !archived);
}
@ -528,42 +539,50 @@ void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() {
Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref);
Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref);
Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref));
log.print("%s indy CP entry [%3d]: %s (%d)",
(archived ? "archived" : "reverted"),
cp_index, cp->pool_holder()->name()->as_C_string(), i);
log.print(" %s %s.%s:%s", (archived ? "=>" : " "), bsm_klass->as_C_string(),
bsm_name->as_C_string(), bsm_signature->as_C_string());
if (resolved) {
log.print("%s indy CP entry [%3d]: %s (%d)",
(archived ? "archived" : "reverted"),
cp_index, cp->pool_holder()->name()->as_C_string(), i);
log.print(" %s %s.%s:%s%s", (archived ? "=>" : " "), bsm_klass->as_C_string(),
bsm_name->as_C_string(), bsm_signature->as_C_string(),
(archived ? "" : " (resolution is not deterministic)"));
}
}
ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived);
}
}
bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry) {
LogStreamHandle(Trace, aot, resolve) log;
bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry, const char*& rejection_reason) {
InstanceKlass* pool_holder = constant_pool()->pool_holder();
if (pool_holder->defined_by_other_loaders()) {
// Archiving resolved cp entries for classes from non-builtin loaders
// is not yet supported.
rejection_reason = "(pool holder comes from a non-builtin loader)";
return false;
}
if (CDSConfig::is_dumping_dynamic_archive()) {
// InstanceKlass::methods() has been resorted. We need to
// update the vtable_index in method_entry (not implemented)
rejection_reason = "(InstanceKlass::methods() has been resorted)";
return false;
}
if (!method_entry->is_resolved(Bytecodes::_invokevirtual)) {
if (method_entry->method() == nullptr) {
rejection_reason = "(method entry is not resolved)";
return false;
}
if (method_entry->method()->is_continuation_native_intrinsic()) {
rejection_reason = "(corresponding stub is generated on demand during method resolution)";
return false; // FIXME: corresponding stub is generated on demand during method resolution (see LinkResolver::resolve_static_call).
}
if (method_entry->is_resolved(Bytecodes::_invokehandle) && !CDSConfig::is_dumping_method_handles()) {
rejection_reason = "(not dumping method handles)";
return false;
}
if (method_entry->method()->is_method_handle_intrinsic() && !CDSConfig::is_dumping_method_handles()) {
rejection_reason = "(not dumping intrinsic method handles)";
return false;
}
}
@ -572,6 +591,7 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv
assert(src_cp->tag_at(cp_index).is_method() || src_cp->tag_at(cp_index).is_interface_method(), "sanity");
if (!AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) {
rejection_reason = "(resolution is not deterministic)";
return false;
}
return true;

View File

@ -226,7 +226,7 @@ class ConstantPoolCache: public MetaspaceObj {
void remove_resolved_field_entries_if_non_deterministic();
void remove_resolved_indy_entries_if_non_deterministic();
void remove_resolved_method_entries_if_non_deterministic();
bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry);
bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry, const char*& rejection_reason);
#endif
// RedefineClasses support

View File

@ -64,6 +64,7 @@ public class AOTLinkedVarHandles {
OutputAnalyzer dumpOut = CDSTestUtils.createArchiveAndCheck(opts);
dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.compareAndExchangeAcquire:\\(\\[DIDI\\)D =>");
dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.get:\\(\\[DI\\)D => ");
dumpOut.shouldNotContain("rejected .* CP entry.*");
CDSOptions runOpts = (new CDSOptions())
.setUseVersion(false)