Calling a lambda expression from a new thread before the main method is run causes the thread to lock up

Luke Hutchison luke.hutch at gmail.com
Tue Jan 24 04:41:46 UTC 2017


If you run the code below, the active JVM thread (in the ExecutorService)
locks up when the lambda expression is called. The Eclipse debugger is not
able to stop the locked-up thread, or get a stacktrace beyond the call into
the lambda.

The problem seems to be that some part of the Java 8 lambda system is not
properly initialized until just before the main method is called. This
problem is only exhibited if you call a lambda expression from a new
thread, spawned by a static initializer block, before the main method is
executed.

Reproducibility: 100%. (If you change the value of either or both of the
static boolean fields, the code completes as expected.)

This problem exists in both Oracle jdk1.8.0_121 and Fedora OpenJDK
1.8.0.111 (64 bit).



import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LambdaBug {

    // Code will hang after "Entering startUp()" if both of these are true
    private static final boolean RUN_AS_STATIC_INITIALIZER = true;
    private static final boolean RUN_USING_LAMBDA = true;

    static {
        if (RUN_AS_STATIC_INITIALIZER) {
            startUp();
        }
    }

    private static void startUp() {
        System.out.println("Entering startUp()");
        ExecutorService es = Executors.newSingleThreadExecutor();
        try {
            Callable<Void> callable;
            if (RUN_USING_LAMBDA) {
                callable = () -> {
                    System.out.println("Lambda executed");
                    return null;
                };
            } else {
                callable = new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        System.out.println("Inner class method executed");
                        return null;
                    }
                };
            }
            es.submit(callable).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        } finally {
            es.shutdown();
        }
        System.out.println("Exiting startUp()");
    }

    public static void main(String[] args) {
        if (!RUN_AS_STATIC_INITIALIZER) {
            startUp();
        }
        System.out.println("Exiting main");
    }
}


More information about the core-libs-dev mailing list