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 07:21:39 UTC 2017


On Mon, Jan 23, 2017 at 10:48 PM, David Holmes <david.holmes at 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.


More information about the core-libs-dev mailing list