JDK-8286927 : Class::forName(String) defaults to system class loader if the caller is null
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang:class_loading
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 19
  • Submitted: 2022-05-17
  • Updated: 2022-06-03
  • Resolved: 2022-05-26
Related Reports
CSR :  
Description
Summary
-------

Specify `Class::forName(String)` to use the system class loader if invoked with no caller frame.

Problem
-------

The `Class::forName(String)` method  is a caller sensitive method but does not specify what should happen when there are no stack frames to determine the caller.  Currently the boot loader is used when there is no caller.  

JNI FindClass uses the system class loader instead if invoked via JNI invocation interface when there is no associated class loader. `Class::forName` when invoked by JNI code with no caller frame should be consistent with JNI FindClass and use the system class loader if caller is null.


Solution
--------

When there is no caller frame on the stack, simply use the system class loader.

Specification
-------------

The spec of java.lang.Class.forName(String) is updated as follows:
```
@@ -357,6 +357,11 @@ public final class Class<T> implements java.io.Serializable,
      * A call to {@code forName("X")} causes the class named
      * {@code X} to be initialized.
      *
+     * <p>
+     * In cases where this method is called from a context where there is no
+     * caller frame on the stack (e.g. when called directly from a JNI
+     * attached thread), the system class loader is used.
+     *
      * @param      className   the fully qualified name of the desired class.
      * @return     the {@code Class} object for the class with the
      *             specified name.

``` 


Comments
Thanks [~mchung]. Moving this CSr to Approved -- leaving the fate of the example to future work. Please consider whether or not a release note is warranted.
26-05-2022

`this.getClass()` implies that this method is invoked from Java, in which case this comment is correct. OTOH, this comment serves more like a see-also `Class.forName(String)` rather than an example. Maybe it can be removed.
26-05-2022

Should the following comment in the three-argument Class.forName be updated as part of this change: > For example, in an instance method the expression: > > Class.forName("Foo") > > is equivalent to: > > Class.forName("Foo", true, this.getClass().getClassLoader())
26-05-2022

The proposal to use the system class loader seems right. Also I agree the compatibility impact is very low or minimal. I doubt there is a lot of code calling this method directly from a JNI attached thread - if there was then we should have seen bug reports from JDK 9+ when some of the defining class loader of some standard classes was changed to the platform class loader.
26-05-2022

I updated the compatibility impact of the change.
25-05-2022

Moving to Provisional, not Approved. [~tprinzing], please say more about the behavioral compatibility impact of this change, what the observed differences could be, etc. Also, I recommend a release note for this change.
23-05-2022