JDK-8275318 : loaded_classes_do may see ArrayKlass before InstanceKlass is loaded
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-10-15
  • Updated: 2022-01-27
  • Resolved: 2022-01-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 19
19 b07Fixed
Related Reports
Relates :  
Description
In the following code, if k is a shared ArrayKlass, it may be passed to klass_closure->do_klass() before its InstanceKlass is in the is_loaded() state.

void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
  // Lock-free access requires load_acquire
  for (Klass* k = Atomic::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(vmClasses::Class_klass()), "invalid mirror");
#endif
      klass_closure->do_klass(k);
    }
  }
}

Scenario:

[1] java/lang/Object is restored via InstanceKlass::restore_unshareable_info()
[2] [Ljava/lang/Object; is restored in when InstanceKlass::restore_unshareable_info() calls array_klasses()->restore_unshareable_info()

At this point, both Klasses are in the ClassLoaderData::_klasses list. However, java/lang/Object is not yet loaded. If another thread calls ClassLoaderData::loaded_classes_do(), it will see the ArrayKlass but not the InstanceKlass.

See discussions in https://github.com/openjdk/jdk/pull/5935
Comments
Changeset: 4f4da3b1 Author: Ioi Lam <iklam@openjdk.org> Date: 2022-01-19 01:35:06 +0000 URL: https://git.openjdk.java.net/jdk/commit/4f4da3b172bb6ed5dd80a144e8eeb17b90bd7cdf
19-01-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk/pull/7069 Date: 2022-01-13 20:57:06 +0000
13-01-2022

It's not easy to create a regression test case for this since only a few shared array classes are created, and most of their "bottom" InstanceKlass are loaded during VM bootstrap. I am marking this bug with noreg-hard.
13-01-2022

ILW=MLM=P4
19-10-2021

Suggested fix: if k is an ObjectArrayKlass, and ObjArrayKlass::cast(k)->bottom_klass() is an InstanceKlass, do not iterate on k unless the bottom_klass is in the loaded state.
15-10-2021

Ok, that sounds like a good fix. [~iklam] did you want to do it?
15-10-2021