On 26/01/2023 7:49 pm, Tagir Valeev wrote:
Hello!

Not sure if this should be considered as a problem that requires
attention but there's an initialization loop between

There are probably still quite a number of "initialization loops" in the core libraries. But they can only trigger if you explicitly load and initialize internal implementation classes. So no, this is not generally considered a problem.

Cheers,
David

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.

Reply via email to