8267954: Shared classes that failed to load should not be loaded again

Reviewed-by: iklam, ccheung
This commit is contained in:
Yumin Qi 2021-06-09 21:33:28 +00:00
parent 991ca14279
commit 7ff6e7b2b1
7 changed files with 51 additions and 36 deletions

View File

@ -956,19 +956,6 @@ InstanceKlass* SystemDictionary::resolve_from_stream(ClassFileStream* st,
#if INCLUDE_CDS
// Load a class for boot loader from the shared spaces. This also
// forces the superclass and all interfaces to be loaded.
InstanceKlass* SystemDictionary::load_shared_boot_class(Symbol* class_name,
PackageEntry* pkg_entry,
TRAPS) {
assert(UseSharedSpaces, "Sanity check");
InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name);
if (ik != NULL && ik->is_shared_boot_class()) {
return load_shared_class(ik, Handle(), Handle(), NULL, pkg_entry, THREAD);
}
return NULL;
}
// Check if a shared class can be loaded by the specific classloader.
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
InstanceKlass* ik,
@ -1289,7 +1276,11 @@ InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Ha
if (UseSharedSpaces)
{
PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
k = load_shared_boot_class(class_name, pkg_entry, THREAD);
InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name);
if (ik != NULL && ik->is_shared_boot_class() && !ik->shared_loading_failed()) {
SharedClassLoadingMark slm(THREAD, ik);
k = load_shared_class(ik, class_loader, Handle(), NULL, pkg_entry, CHECK_NULL);
}
}
#endif
@ -1301,6 +1292,7 @@ InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Ha
// find_or_define_instance_class may return a different InstanceKlass
if (k != NULL) {
CDS_ONLY(SharedClassLoadingMark slm(THREAD, k);)
k = find_or_define_instance_class(class_name, class_loader, k, CHECK_NULL);
}
return k;

View File

@ -376,9 +376,6 @@ protected:
const ClassFileStream *cfs,
PackageEntry* pkg_entry,
TRAPS);
static InstanceKlass* load_shared_boot_class(Symbol* class_name,
PackageEntry* pkg_entry,
TRAPS);
static Handle get_loader_lock_or_null(Handle class_loader);
static InstanceKlass* find_or_define_instance_class(Symbol* class_name,
Handle class_loader,

View File

@ -1018,6 +1018,7 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class(
k = load_shared_class_for_builtin_loader(name, class_loader, THREAD);
if (k != NULL) {
SharedClassLoadingMark slm(THREAD, k);
k = find_or_define_instance_class(name, class_loader, k, CHECK_NULL);
}
}
@ -1047,11 +1048,10 @@ InstanceKlass* SystemDictionaryShared::load_shared_class_for_builtin_loader(
assert(UseSharedSpaces, "must be");
InstanceKlass* ik = find_builtin_class(class_name);
if (ik != NULL) {
if ((ik->is_shared_app_class() &&
SystemDictionary::is_system_class_loader(class_loader())) ||
(ik->is_shared_platform_class() &&
SystemDictionary::is_platform_class_loader(class_loader()))) {
if (ik != NULL && !ik->shared_loading_failed()) {
if ((SystemDictionary::is_system_class_loader(class_loader()) && ik->is_shared_app_class()) ||
(SystemDictionary::is_platform_class_loader(class_loader()) && ik->is_shared_platform_class())) {
SharedClassLoadingMark slm(THREAD, ik);
PackageEntry* pkg_entry = get_package_entry_from_class(ik, class_loader);
Handle protection_domain =
SystemDictionaryShared::init_security_info(class_loader, ik, pkg_entry, CHECK_NULL);

View File

@ -112,6 +112,23 @@ class LambdaProxyClassDictionary;
class RunTimeSharedClassInfo;
class RunTimeSharedDictionary;
class SharedClassLoadingMark {
private:
Thread* THREAD;
InstanceKlass* _klass;
public:
SharedClassLoadingMark(Thread* current, InstanceKlass* ik) : THREAD(current), _klass(ik) {}
~SharedClassLoadingMark() {
assert(THREAD != NULL, "Current thread is NULL");
assert(_klass != NULL, "InstanceKlass is NULL");
if (HAS_PENDING_EXCEPTION) {
if (_klass->is_shared()) {
_klass->set_shared_loading_failed();
}
}
}
};
class SystemDictionaryShared: public SystemDictionary {
friend class ExcludeDumpTimeSharedClasses;
public:

View File

@ -2496,6 +2496,7 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
// before the InstanceKlass is added to the SystemDictionary. Make
// sure the current state is <loaded.
assert(!is_loaded(), "invalid init state");
assert(!shared_loading_failed(), "Must not try to load failed class again");
set_package(loader_data, pkg_entry, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);

View File

@ -207,29 +207,27 @@ class InstanceKlass: public Klass {
// Number of heapOopSize words used by non-static fields in this klass
// (including inherited fields but after header_size()).
int _nonstatic_field_size;
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
int _itable_len; // length of Java itable (in words)
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
int _nonstatic_oop_map_size; // size in words of nonstatic oop map blocks
int _itable_len; // length of Java itable (in words)
// The NestHost attribute. The class info index for the class
// that is the nest-host of this class. This data has not been validated.
u2 _nest_host_index;
u2 _this_class_index; // constant pool entry
u2 _this_class_index; // constant pool entry
u2 _static_oop_field_count; // number of static oop fields in this klass
u2 _java_fields_count; // The number of declared Java fields
u2 _static_oop_field_count;// number of static oop fields in this klass
u2 _java_fields_count; // The number of declared Java fields
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// _is_marked_dependent can be set concurrently, thus cannot be part of the
// _misc_flags.
bool _is_marked_dependent; // used for marking during flushing and deoptimization
bool _is_marked_dependent; // used for marking during flushing and deoptimization
// Class states are defined as ClassState (see above).
// Place the _init_state here to utilize the unused 2-byte after
// _idnum_allocated_count.
u1 _init_state; // state of class
u1 _init_state; // state of class
// This can be used to quickly discriminate among the four kinds of
// InstanceKlass. This should be an enum (?)
@ -250,7 +248,7 @@ class InstanceKlass: public Klass {
_misc_has_nonstatic_concrete_methods = 1 << 5, // class/superclass/implemented interfaces has non-static, concrete methods
_misc_declares_nonstatic_concrete_methods = 1 << 6, // directly declares non-static, concrete methods
_misc_has_been_redefined = 1 << 7, // class has been redefined
_unused = 1 << 8, //
_misc_shared_loading_failed = 1 << 8, // class has been loaded from shared archive
_misc_is_scratch_class = 1 << 9, // class is the redefined scratch class
_misc_is_shared_boot_class = 1 << 10, // defining class loader is boot class loader
_misc_is_shared_platform_class = 1 << 11, // defining class loader is platform class loader
@ -355,6 +353,18 @@ class InstanceKlass: public Klass {
_misc_flags &= ~shared_loader_type_bits();
}
bool shared_loading_failed() const {
return (_misc_flags & _misc_shared_loading_failed) != 0;
}
void set_shared_loading_failed() {
_misc_flags |= _misc_shared_loading_failed;
}
void clear_shared_loading_failed() {
_misc_flags &= ~_misc_shared_loading_failed;
}
void set_shared_class_loader_type(s2 loader_type);
void assign_class_loader_type();

View File

@ -29,8 +29,6 @@
compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java 8268033 generic-x64
runtime/cds/appcds/dynamicArchive/TestDynamicDumpAtOom.java 8267954 linux-x64
vmTestbase/nsk/jvmti/SetFieldAccessWatch/setfldw001/TestDescription.java 8205957 generic-all
vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 windows-x64