Circular initialization between EmptyNavigableMap and UnmodifiableNavigableMap
Tagir Valeev
amaembo at gmail.com
Thu Jan 26 09:49:13 UTC 2023
Hello!
Not sure if this should be considered as a problem that requires
attention but there's an initialization loop between
java.util.Collections$UnmodifiableNavigableMap and
java.util.Collections$UnmodifiableNavigableMap$EmptyNavigableMap
classes. E.g., the following program may stuck in a classloader
deadlock (happens to me in ~30% of launches):
import static java.util.concurrent.CompletableFuture.supplyAsync;
public class Test {
public static void main(String[] args) {
var future1 = supplyAsync(() ->
loadClass("java.util.Collections$UnmodifiableNavigableMap$EmptyNavigableMap"));
var future2 = supplyAsync(() ->
loadClass("java.util.Collections$UnmodifiableNavigableMap"));
System.out.println(future1.join()+":"+future2.join());
}
private static Class<?> loadClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
This is due to the EMPTY_NAVIGABLE_MAP which is declared in
UnmodifiableNavigableMap but its type is a subclass of
UnmodifiableNavigableMap. Moving the field inside EmptyNavigableMap
will likely solve the problem. On the other hand, I was not able to
reproduce the problem without explicit Class.forName call, and given
that EmptyNavigableMap class is an implementation detail, we probably
can ignore this.
With best regards,
Tagir Valeev.
More information about the core-libs-dev
mailing list