On Mon, Jan 23, 2017 at 10:48 PM, David Holmes <david.hol...@oracle.com> wrote:
> On 24/01/2017 2:41 PM, Luke Hutchison wrote: > >> 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. >> > > That looks like a variation of the classic class initialization deadlock > problem. Your main thread is blocked in es.submit(callable).get(); while > still within the static initializer of the LambdaBug class. If the executor > thread also needs to ensure LambdaBug is initialized (which it will in the > lambda case) then it will wait for the main thread to complete the > initialization. Hence deadlock. > Thanks for the explanation -- although I don't understand why a lambda expression requires its defining class to be initialized, whereas an anonymous inner class does not. The lambda body does not refer to the LambdaBug class. This must be due to an implicit reference to the defining class being added by the compiler for purposes of capturing the lexical scope (with this issue not getting triggered in the case of anonymous inner classes due to scoping differences)? However, why is the containing class reference even used in this case, when variables in the containing scope are not referenced? If this is due to lexical scoping, shouldn't the compiler be able to add some runtime code to detect cases of this kind of deadlock, and throw a RuntimeException, or potentially even detect some of these cases statically? Why is it possible to directly call lambdas inside a static initializer block without causing a deadlock (in other words, why is there no deadlock as long as the lambdas are not executed on a different thread while the main thread blocks)? The calling class is still not completely initialized when calling lambdas directly in a static initializer block on the main thread.