diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index be02d006793..375d93678d2 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1106,45 +1106,11 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle return true; } -// Pre-load class referred to in non-static null-free instance field. These fields trigger MANDATORY loading. -// Some pre-loading does not fail fatally -bool SystemDictionary::preload_from_null_free_field(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) { - TempNewSymbol name = Signature::strip_envelope(sig); - log_info(class, preload)("Preloading of class %s during loading of shared class %s. " - "Cause: a null-free non-static field is declared with this type", - name->as_C_string(), ik->name()->as_C_string()); - InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection(ik->name(), name, - class_loader, false, CHECK_false); - if (HAS_PENDING_EXCEPTION) { - log_info(class, preload)("Preloading of class %s during loading of class %s " - "(cause: null-free non-static field) failed: %s", - name->as_C_string(), ik->name()->as_C_string(), - PENDING_EXCEPTION->klass()->name()->as_C_string()); - return false; // Exception is still pending - } - - InstanceKlass* k = ik->get_inline_type_field_klass_or_null(field_index); - if (real_k != k) { - // oops, the app has substituted a different version of k! Does not fail fatally - log_info(class, preload)("Preloading of class %s during loading of shared class %s " - "(cause: null-free non-static field) failed : " - "app substituted a different version", - name->as_C_string(), ik->name()->as_C_string()); - return false; - } - log_info(class, preload)("Preloading of class %s during loading of shared class %s " - "(cause: null-free non-static field) succeeded", - name->as_C_string(), ik->name()->as_C_string()); - - assert(real_k != nullptr, "Sanity check"); - InstanceKlass::check_can_be_annotated_with_NullRestricted(real_k, ik->name(), CHECK_false); - - return true; -} - -// Tries to pre-load classes referred to in non-static nullable instance fields if they are found in the -// loadable descriptors attribute. If loading fails, we can fail silently. -void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) { +// Tries to pre-load classes referred to in non-static instance fields if they are found in the +// loadable descriptors attribute. If loading fails, we can fail silently unless the shared class +// has archived null-restricted field metadata that must be checked against the resolved class. +bool SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, + int field_index, bool validate_field_klass, TRAPS) { TempNewSymbol name = Signature::strip_envelope(sig); if (name != ik->name() && ik->is_class_in_loadable_descriptors_attribute(sig)) { log_info(class, preload)("Preloading of class %s during loading of shared class %s. " @@ -1153,7 +1119,14 @@ void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection(ik->name(), name, class_loader, false, THREAD); if (HAS_PENDING_EXCEPTION) { + if (validate_field_klass) { + log_info(class, preload)("Preloading of class %s during loading of shared class %s " + "(cause: field type in LoadableDescriptors attribute) failed : %s", + name->as_C_string(), ik->name()->as_C_string(), + PENDING_EXCEPTION->klass()->name()->as_C_string()); + } CLEAR_PENDING_EXCEPTION; + return !validate_field_klass; } InstanceKlass* k = ik->get_inline_type_field_klass_or_null(field_index); @@ -1163,13 +1136,14 @@ void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, "(cause: field type in LoadableDescriptors attribute) failed : " "app substituted a different version", name->as_C_string(), ik->name()->as_C_string()); - return; + return !validate_field_klass; } else if (real_k != nullptr) { log_info(class, preload)("Preloading of class %s during loading of shared class %s " "(cause: field type in LoadableDescriptors attribute) succeeded", name->as_C_string(), ik->name()->as_C_string()); } } + return true; } @@ -1203,16 +1177,16 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, Symbol* sig = fs.signature(); int field_index = fs.index(); - if (fs.is_null_free_inline_type()) { - // A false return means that the class didn't load for other reasons than an exception. - bool check = preload_from_null_free_field(ik, class_loader, sig, field_index, CHECK_NULL); + if (Signature::has_envelope(sig)) { + // Pending exceptions are cleared so preload failures can fail silently unless archived + // null-restricted field metadata must be checked against the resolved class. + bool validate_field_klass = fs.is_null_free_inline_type(); + bool check = try_preload_from_loadable_descriptors(ik, class_loader, sig, field_index, + validate_field_klass, CHECK_NULL); if (!check) { ik->set_shared_loading_failed(); return nullptr; } - } else if (Signature::has_envelope(sig)) { - // Pending exceptions are cleared so we can fail silently - try_preload_from_loadable_descriptors(ik, class_loader, sig, field_index, CHECK_NULL); } } } diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 7ecfe34a96a..7350227af09 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -331,8 +331,8 @@ class SystemDictionary : AllStatic { static bool add_loader_constraint(Symbol* name, Klass* klass_being_linked, Handle loader1, Handle loader2); - static bool preload_from_null_free_field(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS); - static void try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS); + static bool try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, + int field_index, bool validate_field_klass, TRAPS); static InstanceKlass* load_shared_class(InstanceKlass* ik, Handle class_loader, Handle protection_domain,