From 52e777845f0a09b4c285131f1eff02dfbffa0d1f Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 25 Sep 2025 19:59:52 +0000 Subject: [PATCH] 8367910: Reduce warnings about unsupported classes in AOT cache creation Reviewed-by: dholmes, kvn, shade --- .../share/cds/dumpTimeClassInfo.inline.hpp | 2 +- .../classfile/systemDictionaryShared.cpp | 63 +++++++++++-------- .../classfile/systemDictionaryShared.hpp | 3 +- src/hotspot/share/classfile/verifier.cpp | 2 +- src/hotspot/share/oops/trainingData.cpp | 2 +- .../cds/appcds/aotCache/OldClassSupport.java | 1 + .../cds/appcds/aotCache/VerifierFailOver.java | 2 +- .../aotClassLinking/BulkLoaderTest.java | 2 +- 8 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp index 90f35c61de1..658d3d31e50 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp @@ -53,7 +53,7 @@ void DumpTimeSharedClassTable::iterate_all_live_classes(Function function) const assert(k->is_loader_alive(), "must not change"); } else { if (!SystemDictionaryShared::is_excluded_class(k)) { - SystemDictionaryShared::warn_excluded(k, "Class loader not alive"); + SystemDictionaryShared::log_exclusion(k, "Class loader not alive"); SystemDictionaryShared::set_excluded_locked(k); } } diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 04c2d7ffb84..da022436292 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -354,11 +354,13 @@ void SystemDictionaryShared::check_exclusion_for_self_and_dependencies(InstanceK }); } -// Returns true so the caller can do: return warn_excluded("....."); -bool SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) { +void SystemDictionaryShared::log_exclusion(InstanceKlass* k, const char* reason, bool is_warning) { ResourceMark rm; - aot_log_warning(aot)("Skipping %s: %s", k->name()->as_C_string(), reason); - return true; + if (is_warning) { + aot_log_warning(aot)("Skipping %s: %s", k->name()->as_C_string(), reason); + } else { + aot_log_info(aot)("Skipping %s: %s", k->name()->as_C_string(), reason); + } } bool SystemDictionaryShared::is_jfr_event_class(InstanceKlass *k) { @@ -377,23 +379,35 @@ bool SystemDictionaryShared::is_early_klass(InstanceKlass* ik) { } bool SystemDictionaryShared::check_self_exclusion(InstanceKlass* k) { + bool log_warning = false; + const char* error = check_self_exclusion_helper(k, log_warning); + if (error != nullptr) { + log_exclusion(k, error, log_warning); + return true; // Should be excluded + } else { + return false; // Should not be excluded + } +} + +const char* SystemDictionaryShared::check_self_exclusion_helper(InstanceKlass* k, bool& log_warning) { assert_lock_strong(DumpTimeTable_lock); if (CDSConfig::is_dumping_final_static_archive() && k->defined_by_other_loaders() && k->in_aot_cache()) { - return false; // Do not exclude: unregistered classes are passed from preimage to final image. + return nullptr; // Do not exclude: unregistered classes are passed from preimage to final image. } if (k->is_in_error_state()) { - return warn_excluded(k, "In error state"); + log_warning = true; + return "In error state"; } if (k->is_scratch_class()) { - return warn_excluded(k, "A scratch class"); + return "A scratch class"; } if (!k->is_loaded()) { - return warn_excluded(k, "Not in loaded state"); + return "Not in loaded state"; } if (has_been_redefined(k)) { - return warn_excluded(k, "Has been redefined"); + return "Has been redefined"; } if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) { if (k->name()->starts_with("java/lang/invoke/BoundMethodHandle$Species_")) { @@ -401,43 +415,42 @@ bool SystemDictionaryShared::check_self_exclusion(InstanceKlass* k) { if (CDSConfig::is_dumping_method_handles()) { k->set_shared_classpath_index(0); } else { - ResourceMark rm; - aot_log_info(aot)("Skipping %s because it is dynamically generated", k->name()->as_C_string()); - return true; // exclude without warning + return "dynamically generated"; } } else { // These are classes loaded from unsupported locations (such as those loaded by JVMTI native // agent during dump time). - return warn_excluded(k, "Unsupported location"); + return "Unsupported location"; } } if (k->signers() != nullptr) { // We cannot include signed classes in the archive because the certificates // used during dump time may be different than those used during // runtime (due to expiration, etc). - return warn_excluded(k, "Signed JAR"); + return "Signed JAR"; } if (is_jfr_event_class(k)) { // We cannot include JFR event classes because they need runtime-specific // instrumentation in order to work with -XX:FlightRecorderOptions:retransform=false. // There are only a small number of these classes, so it's not worthwhile to // support them and make CDS more complicated. - return warn_excluded(k, "JFR event class"); + return "JFR event class"; } if (!k->is_linked()) { if (has_class_failed_verification(k)) { - return warn_excluded(k, "Failed verification"); + log_warning = true; + return "Failed verification"; } else if (CDSConfig::is_dumping_aot_linked_classes()) { // Most loaded classes should have been speculatively linked by AOTMetaspace::link_class_for_cds(). // Old classes may not be linked if CDSConfig::is_preserving_verification_constraints()==false. // An unlinked class may fail to verify in AOTLinkedClassBulkLoader::init_required_classes_for_loader(), // causing the JVM to fail at bootstrap. - return warn_excluded(k, "Unlinked class not supported by AOTClassLinking"); + return "Unlinked class not supported by AOTClassLinking"; } else if (CDSConfig::is_dumping_preimage_static_archive()) { // When dumping the final static archive, we will unconditionally load and link all // classes from the preimage. We don't want to get a VerifyError when linking this class. - return warn_excluded(k, "Unlinked class not supported by AOTConfiguration"); + return "Unlinked class not supported by AOTConfiguration"; } } else { if (!k->can_be_verified_at_dumptime()) { @@ -447,17 +460,15 @@ bool SystemDictionaryShared::check_self_exclusion(InstanceKlass* k) { // won't work at runtime. // As a result, we cannot store this class. It must be loaded and fully verified // at runtime. - return warn_excluded(k, "Old class has been linked"); + return "Old class has been linked"; } } if (UnregisteredClasses::check_for_exclusion(k)) { - ResourceMark rm; - aot_log_info(aot)("Skipping %s: used only when dumping CDS archive", k->name()->as_C_string()); - return true; + return "used only when dumping CDS archive"; } - return false; + return nullptr; } // Returns true if DumpTimeClassInfo::is_excluded() is true for at least one of k's exclusion dependencies. @@ -511,7 +522,7 @@ bool SystemDictionaryShared::is_dependency_excluded(InstanceKlass* k, InstanceKl DumpTimeClassInfo* dependency_info = get_info_locked(dependency); if (dependency_info->is_excluded()) { ResourceMark rm; - aot_log_warning(aot)("Skipping %s: %s %s is excluded", k->name()->as_C_string(), type, dependency->name()->as_C_string()); + aot_log_info(aot)("Skipping %s: %s %s is excluded", k->name()->as_C_string(), type, dependency->name()->as_C_string()); return true; } return false; @@ -838,7 +849,7 @@ public: InstanceKlass* k = _list.at(i); bool i_am_first = SystemDictionaryShared::add_unregistered_class(_thread, k); if (!i_am_first) { - SystemDictionaryShared::warn_excluded(k, "Duplicated unregistered class"); + SystemDictionaryShared::log_exclusion(k, "Duplicated unregistered class"); SystemDictionaryShared::set_excluded_locked(k); } } @@ -967,7 +978,7 @@ bool SystemDictionaryShared::has_class_failed_verification(InstanceKlass* ik) { } void SystemDictionaryShared::set_from_class_file_load_hook(InstanceKlass* ik) { - warn_excluded(ik, "From ClassFileLoadHook"); + log_exclusion(ik, "From ClassFileLoadHook"); set_excluded(ik); } diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index baad020cb61..5ff57653dd0 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -180,6 +180,7 @@ private: // exclusion checks static void check_exclusion_for_self_and_dependencies(InstanceKlass *k); static bool check_self_exclusion(InstanceKlass* k); + static const char* check_self_exclusion_helper(InstanceKlass* k, bool& log_warning); static bool check_dependencies_exclusion(InstanceKlass* k, DumpTimeClassInfo* info); static bool check_verification_constraint_exclusion(InstanceKlass* k, Symbol* constraint_class_name); static bool is_dependency_excluded(InstanceKlass* k, InstanceKlass* dependency, const char* type); @@ -277,7 +278,7 @@ public: static void set_excluded(InstanceKlass* k); static void set_excluded_locked(InstanceKlass* k); static void set_from_class_file_load_hook(InstanceKlass* k) NOT_CDS_RETURN; - static bool warn_excluded(InstanceKlass* k, const char* reason); + static void log_exclusion(InstanceKlass* k, const char* reason, bool is_warning = false); static void dumptime_classes_do(class MetaspaceClosure* it); static void write_to_archive(bool is_static_archive = true); static void serialize_dictionary_headers(class SerializeClosure* soc, diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index f6f5aa70fbd..bc278f3d158 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -237,7 +237,7 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) { // Exclude any classes that are verified with the old verifier, as the old verifier // doesn't call SystemDictionaryShared::add_verification_constraint() if (CDSConfig::is_dumping_archive()) { - SystemDictionaryShared::warn_excluded(klass, "Verified with old verifier"); + SystemDictionaryShared::log_exclusion(klass, "Verified with old verifier"); SystemDictionaryShared::set_excluded(klass); } #endif diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index c768d13fe59..41fbc6de994 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -618,7 +618,7 @@ void CompileTrainingData::verify(bool verify_dep_counter) { for (int i = 0; i < init_dep_count(); i++) { KlassTrainingData* ktd = init_dep(i); if (ktd->has_holder() && ktd->holder()->defined_by_other_loaders()) { - LogStreamHandle(Warning, training) log; + LogStreamHandle(Info, training) log; if (log.is_enabled()) { ResourceMark rm; log.print("CTD "); print_value_on(&log); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport.java index 42161b469bf..732ef4f2810 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/OldClassSupport.java @@ -65,6 +65,7 @@ public class OldClassSupport { @Override public String[] vmArgs(RunMode runMode) { return new String[] { + "-Xlog:aot", "-Xlog:aot+class=debug", "-Xlog:aot+resolve=trace", }; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java index 50b47e4424d..8107e3fe0a3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/VerifierFailOver.java @@ -39,7 +39,7 @@ import jdk.test.lib.process.OutputAnalyzer; public class VerifierFailOver { public static void main(String... args) throws Exception { SimpleCDSAppTester.of("VerifierFailOver") - .addVmArgs("-Xlog:aot+class=debug") + .addVmArgs("-Xlog:aot,aot+class=debug") .classpath("app.jar") .appCommandLine("VerifierFailOverApp") .setTrainingChecker((OutputAnalyzer out) -> { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java index 9e43d00e872..482f8fb4ad0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -118,7 +118,7 @@ public class BulkLoaderTest { @Override public String[] vmArgs(RunMode runMode) { return new String[] { - "-Xlog:cds,aot+load,cds+class=debug,aot+class=debug", + "-Xlog:cds,aot,aot+load,cds+class=debug,aot+class=debug", "-XX:+AOTClassLinking", }; }