Circular initialization between EmptyNavigableMap and UnmodifiableNavigableMap
David Holmes
david.holmes at oracle.com
Mon Jan 30 07:50:18 UTC 2023
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.
More information about the core-libs-dev
mailing list