On Wed, 9 Apr 2025 09:03:41 GMT, Timofei Pushkin <tpush...@openjdk.org> wrote:

>> src/java.base/share/classes/jdk/internal/misc/CDS.java line 438:
>> 
>>> 436:             // class loader. Thus it is safe to delegate their loading 
>>> to system class loader
>>> 437:             // (our parent) - this is what the default implementation 
>>> of loadClass() will do.
>>> 438:             return defineClass(name, bytes, 0, bytes.length);
>> 
>> I didn't realize that `URLClassLoader` will by default delegate to 
>> `ClassLoader::getSystemClassLoader()`. How about rewording the comments like 
>> this to clarify?
>> 
>> 
>> // defineClass() will internally invoke loadClass() to load supertypes of 
>> this unregistered class.
>> // Any supertype S with the name SN must have already been loaded (enforced 
>> by the order
>> // of classes in the classlist). In addition:
>> // - if S is an unregistered class, S must have already been have been 
>> defined by the current class
>> //   loader, and will be found by `this.findLoadedClass(SN)`
>> // - if S is not an unregistered class, S must have already been defined by 
>> the built-in boot,
>> //   platform, or system class loaders, and can be found by 
>> this.getParent().loadClass(SN, false)
>> // See the implementation of ClassLoader::loadClass() for details.
>> //
>> // Therefore, we should resolve all supertypes to the expected ones as 
>> specified by the
>> // <code>super:</code> and <code>interfaces:</code> attributes in the 
>> classlist. This
>> // invariance is validated by the C++ function 
>> ClassListParser::load_class_from_source()
>> assert getParent() == getSystemClassLoader();
>> return defineClass(name, bytes, 0, bytes.length);
>
> I've actually noticed a problem here. I assumed that registered classes are 
> always loaded by JDK's built-in class loaders (bootstrap, 
> `jdk.internal.loader.ClassLoaders$PlatformClassLoader` or 
> `jdk.internal.loader.ClassLoaders$AppClassLoader`). But in reality when the 
> system class loader is user-provided (via 
> `-Djava.system.class.loader=<class>`) classes loaded by it are still 
> considered registered. This is a problem because such user-provided class 
> loader may not delegate to real built-in class loaders.
> 
> For example:
> - Let C=<N, L> be a class C named N defined by class loader L
> - Let AppL be the built-in system class loader and SysL be the user-provided 
> system class loader
> - Let U be an unregistered class which extends a registered <S, AppL>
> - Let SysL be able to load a registered <S, SysL> when requested (i.e. SysL 
> doesn't delegate when loading a class named S)
> - When `UnregisteredClassLoader` will be loading U it will delegate the 
> loading of its super named S to SysL and thus <S, SysL> will become a super 
> of U instead of <S, AppL> — this is not correct
> 
> This won't be a problem if only classes loaded by the real built-in class 
> loaders would be considered registered because such class loaders always 
> delegate first (the 4th bullet above won't be possible), and thus it doesn't 
> matter which of these loaders was used for delegation by the class loader 
> which defined U.
> 
> This can't be fixed by just making 
> `jdk.internal.loader.ClassLoaders$AppClassLoader` a parent of 
> `UnregisteredClassLoader` and making 
> `UnregisteredClassLoader.findClass(name)` return 
> `getSystemClassLoader().loadClass(name)` because then the case when U extends 
> <S, SysL> will not be handeled correctly (<S, AppL> will be used instead of 
> <S, SysL>).
> 
> So it looks like I have to revert this delegation-based approach and use the 
> old way. I'll also write a test from the above example to see if I am correct 
> first.

I've realized that my example above cannot be expressed in the current class 
list format since the format doesn't distinguish between <S, SysL> and <S, 
AppL>, only that S is not unregistered. The existing implementation (without 
this PR) will always use <S, SysL>. It feels like a flaw to me but it is not a 
flaw of this patch.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/24223#discussion_r2035755124

Reply via email to