<div dir="ltr">Hi! In the following test case I've investigated how Hotspot loads classes into the loaders.<br>And found out that the inheritance chain could affect the result.<br><br>//--------------------------------------------------------------------------<br>public class SimpleTest {<br>    public static int compare(ScheduledFutureTask o1, ScheduledFutureTask o2) {<br>        return o1.compareTo(o2);<br>    }<br><br>    public static void main(String[] args) {<br>        ScheduledFutureTask instances0 = new ScheduledFutureTask();<br>        ScheduledFutureTask instances1 = new ScheduledFutureTask();<br>        compare(instances0, instances1);<br>    }<br>}<br><br>final class ScheduledFutureTask implements ScheduledFuture<Void> {<br>...<br>    @Override<br>    public int compareTo(Delayed o) {<br>        if (this == o) {<br>            return 0;<br>        }<br>    }<br>}<br>//--------------------------------------------------------------------------<br><br><ul><li style="margin-left:15px">If <i>ScheduledFutureTask</i> class implements <i>java.util.concurrent.ScheduledFuture </i>interface,</li></ul>which implements <i>java.util.concurrent.Delayed</i> interface: <b>[application class -> core class -> core class],</b><br>then the <i>Delayed </i>interface would be loaded into the boot class loader, since it's resolved in the context of the core class.<br><br>I've added some logs to track class resolving:<br># parse interfaces of class ScheduledFutureTask, [APP] loader<br># parse interfaces of class java/util/concurrent/ScheduledFuture, [BOOT] loader<br># parse interfaces of class java/util/concurrent/Delayed, [BOOT] loader<br># Adding java/util/concurrent/Delayed to dictionary [BOOT]<br><br><ul><li style="margin-left:15px">If we replace core class in the chain with an application one: <b>[application class -> application class -> core class], </b></li></ul>then the <i>Delayed </i>interface would be loaded into both class loaders, since it would be resolved in the context of the application class:<br><br># parse interfaces of class ScheduledFutureTask, [application class loader]<br># parse interfaces of class Interface1, [application class loader]<br># parse interfaces of class java/util/concurrent/Delayed, [boot class loader]<br># Adding java/util/concurrent/Delayed to dictionary [boot class loader]<br># Adding java/util/concurrent/Delayed to dictionary [application class loader]<br><br><ul><li style="margin-left:15px">Theoretically, this difference could affect the result of the has_unloaded_classes_in_signature() call</li></ul>for the ScheduledFutureTask::compareTo method.<br><br>final class ScheduledFutureTask implements ScheduledFuture<Void> {<br>...<br>    @Override<br>    public int compareTo(Delayed o) {<br>        if (this == o) {<br>            return 0;<br>        }<br>    }<br>}<br><br>Because in the first case (application class -> core class -> core class) we have unloaded <i>java/util/concurrent/Delayed</i> <div>interface in the context of the accessing class, which was loaded into the application class loader.<br><br>So my question is: why is it correct to have class loaded into different class loaders depending on the inheritance chain?<br>Or maybe it's intentionally resolved somewhere in the code?<div><p>Note that SystemDictionary::check_signature_loaders doesn't add loader constraints to the interface, since the caller and callee loaders are the same in this case: both application loaders. </p>Thank you!</div></div></div>