Currently, a shared InstanceKlass can be loaded (from the CDS archive) at most once. Inside load_shared_class(), many internal states of the InstanceKlass are restored. We will run into problems if
- two threads try to concurrently call load_shared_class on the same InstanceKlass. They will race in restoring the internal states
- We try to load the InstanceKlass and it fails due to OutOfMemoryError. If we try to load it again, the restoring code may fail because the class is in an inconsistent state.
There's already code in the SystemDictionary to avoid loading the same shared class twice. E.g.
https://github.com/openjdk/jdk/blob/b062b1bd8126610d9288dc179d69e54a40b81015/src/hotspot/share/classfile/systemDictionary.cpp#L646-L652
- The boot loader uses the placeholder table to allow a single thread to load a class/classloader pair.
- The platform/app loaders are parallelCapable. They use a per-class lock to allow a single thread to come to here for each class_name
This RFE adds asserts to make sure that the above logic indeed works.
Proposed solution:
- add a debug-only field InstanceKlass::_shared_class_load_count
- At the beginning of load_shared_class, increment this field by one
- Assert if the new value is not 1
- two threads try to concurrently call load_shared_class on the same InstanceKlass. They will race in restoring the internal states
- We try to load the InstanceKlass and it fails due to OutOfMemoryError. If we try to load it again, the restoring code may fail because the class is in an inconsistent state.
There's already code in the SystemDictionary to avoid loading the same shared class twice. E.g.
https://github.com/openjdk/jdk/blob/b062b1bd8126610d9288dc179d69e54a40b81015/src/hotspot/share/classfile/systemDictionary.cpp#L646-L652
- The boot loader uses the placeholder table to allow a single thread to load a class/classloader pair.
- The platform/app loaders are parallelCapable. They use a per-class lock to allow a single thread to come to here for each class_name
This RFE adds asserts to make sure that the above logic indeed works.
Proposed solution:
- add a debug-only field InstanceKlass::_shared_class_load_count
- At the beginning of load_shared_class, increment this field by one
- Assert if the new value is not 1