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");
    }
}

Reply via email to