8210926: vmTestbase/nsk/jvmti/scenarios/allocation/AP11/ap11t001/TestDescription.java failed with JVMTI_ERROR_INVALID_CLASS in CDS mode
Summary: Reset InstanceKlass _init_state to 'allocated' before writing out shared classes at dump time.
Reviewed-by: dholmes, coleenp
--- a/src/hotspot/share/classfile/classLoaderData.cpp Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Mon Oct 01 00:52:37 2018 -0400
@@ -338,6 +338,11 @@
for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
// Do not filter ArrayKlass oops here...
if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
+#ifdef ASSERT
+ oop m = k->java_mirror();
+ assert(m != NULL, "NULL mirror");
+ assert(m->is_a(SystemDictionary::Class_klass()), "invalid mirror");
+#endif
klass_closure->do_klass(k);
}
}
--- a/src/hotspot/share/oops/instanceKlass.cpp Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Mon Oct 01 00:52:37 2018 -0400
@@ -686,15 +686,6 @@
return Verifier::verify(this, should_verify_class(), THREAD);
}
-
-// Used exclusively by the shared spaces dump mechanism to prevent
-// classes mapped into the shared regions in new VMs from appearing linked.
-
-void InstanceKlass::unlink_class() {
- assert(is_linked(), "must be linked");
- _init_state = loaded;
-}
-
void InstanceKlass::link_class(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
@@ -2300,10 +2291,12 @@
return;
}
- // Unlink the class
- if (is_linked()) {
- unlink_class();
- }
+ // Reset to the 'allocated' state to prevent any premature accessing to
+ // a shared class at runtime while the class is still being loaded and
+ // restored. A class' init_state is set to 'loaded' at runtime when it's
+ // being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()).
+ _init_state = allocated;
+
{
MutexLocker ml(Compile_lock);
init_implementor();
@@ -2350,6 +2343,10 @@
}
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+ // SystemDictionary::add_to_hierarchy() sets the init_state to loaded
+ // before the InstanceKlass is added to the SystemDictionary. Make
+ // sure the current state is <loaded.
+ assert(!is_loaded(), "invalid init state");
set_package(loader_data, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
--- a/src/hotspot/share/oops/instanceKlass.hpp Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp Mon Oct 01 00:52:37 2018 -0400
@@ -542,7 +542,6 @@
void initialize(TRAPS);
void link_class(TRAPS);
bool link_class_or_fail(TRAPS); // returns false on failure
- void unlink_class();
void rewrite_class(TRAPS);
void link_methods(TRAPS);
Method* class_initializer() const;