Resolving super interface in different contexts depending on the child class
Aleksandr Popov
a.popov.tmb at gmail.com
Fri Feb 23 16:32:49 UTC 2024
Hi! In the following test case I've investigated how Hotspot loads classes
into the loaders.
And found out that the inheritance chain could affect the result.
//--------------------------------------------------------------------------
public class SimpleTest {
public static int compare(ScheduledFutureTask o1, ScheduledFutureTask
o2) {
return o1.compareTo(o2);
}
public static void main(String[] args) {
ScheduledFutureTask instances0 = new ScheduledFutureTask();
ScheduledFutureTask instances1 = new ScheduledFutureTask();
compare(instances0, instances1);
}
}
final class ScheduledFutureTask implements ScheduledFuture<Void> {
...
@Override
public int compareTo(Delayed o) {
if (this == o) {
return 0;
}
}
}
//--------------------------------------------------------------------------
- If *ScheduledFutureTask* class implements
*java.util.concurrent.ScheduledFuture *interface,
which implements *java.util.concurrent.Delayed* interface: *[application
class -> core class -> core class],*
then the *Delayed *interface would be loaded into the boot class loader,
since it's resolved in the context of the core class.
I've added some logs to track class resolving:
# parse interfaces of class ScheduledFutureTask, [APP] loader
# parse interfaces of class java/util/concurrent/ScheduledFuture, [BOOT]
loader
# parse interfaces of class java/util/concurrent/Delayed, [BOOT] loader
# Adding java/util/concurrent/Delayed to dictionary [BOOT]
- If we replace core class in the chain with an application one:
*[application
class -> application class -> core class], *
then the *Delayed *interface would be loaded into both class loaders, since
it would be resolved in the context of the application class:
# parse interfaces of class ScheduledFutureTask, [application class loader]
# parse interfaces of class Interface1, [application class loader]
# parse interfaces of class java/util/concurrent/Delayed, [boot class
loader]
# Adding java/util/concurrent/Delayed to dictionary [boot class loader]
# Adding java/util/concurrent/Delayed to dictionary [application class
loader]
- Theoretically, this difference could affect the result of the
has_unloaded_classes_in_signature() call
for the ScheduledFutureTask::compareTo method.
final class ScheduledFutureTask implements ScheduledFuture<Void> {
...
@Override
public int compareTo(Delayed o) {
if (this == o) {
return 0;
}
}
}
Because in the first case (application class -> core class -> core class)
we have unloaded *java/util/concurrent/Delayed*
interface in the context of the accessing class, which was loaded into the
application class loader.
So my question is: why is it correct to have class loaded into different
class loaders depending on the inheritance chain?
Or maybe it's intentionally resolved somewhere in the code?
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.
Thank you!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-dev/attachments/20240223/1de8a552/attachment-0001.htm>
More information about the hotspot-dev
mailing list