On Wed, 9 Apr 2025 16:43:39 GMT, Timofei Pushkin <tpush...@openjdk.org> wrote:
>> 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 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 will always use > <S, SysL> as will the new one. It feels like a flaw to me but it is not a > flaw of this patch. Currently we have some restrictions if`-Djava.system.class.loader=` is specified - we disable full module graph archiving: https://github.com/openjdk/jdk/blob/0e223f1456c14efdb423595bee3444d5e26db7c6/src/hotspot/share/cds/cdsConfig.cpp#L286 - we disable loading archived classes for platform and system loaders: https://github.com/openjdk/jdk/blob/0e223f1456c14efdb423595bee3444d5e26db7c6/src/hotspot/share/cds/filemap.cpp#L1874-L1886 I think we should extend this limitation further (in a separate issue) - At dump time, dump only boot classes (no platform, system or unregistered) - At run time, load only boot classes (no platform, system or unregistered) I filed [JDK-8354315](https://bugs.openjdk.org/browse/JDK-8354315) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24223#discussion_r2037729803