Community
Participate
Working Groups
I20151207-2000 The stack frame for a Lambda doesn't provide enough context in the debugger. Example: package xy; public class LambdaDebugging { public static void main(String[] args) { String message = "Hello World"; Thread thread= new Thread() { @Override public void run() { System.out.println(message); // Breakpoint } }; thread.start(); Runnable runnable= () -> { System.out.println(message); // Breakpoint System.out.println(message + 2); }; runnable.run(); } } In the lambda, I can't write a breakpoint condition that refers to the variable 'message', e.g. 'message.contains("or")'. Content assist supports 'message', but when the breakpoint is hit, I get a Conditional Breakpoint Error (message cannot be resolved). It's also hard to debug the lambda body, because the Variables view only shows the captured local variables when the second stack frame is selected: Debug view; LambdaDebugging.lambda$0(String) line: 14 104739310.run() line: not available LambdaDebugging.main(String[]) line: 17 Variables view (selection: 104739310.run()...): this= 104739310 (id=30) arg$1= "Hello World" (id=31) If the debug protocol doesn't provide more information in the topmost stack frame, then JDT Debug may have to inject a custom "this" with properly named children (e.g. val$message or arg$message instead of arg$1). This should also be used in the Variable Values hover, which also doesn't work when a thread is suspended in a lambda body.
Bug 422015 also contains some discussion of this problem. The problem here is that the function object created by the lambda metafactory is an implementation detail of the runtime, and even the order of the captured variables ('messages' in this case) is a compiler implementation detail. Yes, we can make assumptions about either, but we can't guarantee that it would continue to work in the future.
Another thing: The Variable Values hover does work for lambda expressions, just not for captured variables in the lambda expressions outer scope. Consider this class, paused at breakpoint 3. Here will both 'lambdaParameter' and 'this.instanceField' show contents on hovering, but 'effectivelyFinal' and 'effectivelyFinalMethodParameter' will not: import java.util.function.Consumer; public class LambdaDebugging { public static String staticField = "Static Field"; public String instanceField = "Instance Field"; public static void main(String[] args) { new LambdaDebugging().someMethod("Effectively Final Method Parameter"); } void someMethod(String effectivelyFinalMethodParameter) { String effectivelyFinal = "Effectively Final"; Consumer<String> anonymousConsumer = new Consumer<String>() { public void accept(String parameter) { System.out.println("effectivelyFinalMethodParameter is '" + effectivelyFinalMethodParameter + "'"); // Breakpoint 1 System.out.println("effectivelyFinal is '" + effectivelyFinal + "'"); System.out.println("parameter is '" + parameter + "'"); } }; anonymousConsumer.accept("Parameter"); Consumer<String> staticLambda = (lambdaParameter) -> { System.out.println("effectivelyFinalMethodParameter is '" + effectivelyFinalMethodParameter + "'"); // Breakpoint 2 System.out.println("effectivelyFinal is '" + effectivelyFinal + "'"); System.out.println("lambdaParameter is '" + lambdaParameter + "'"); }; staticLambda.accept("Lambda Parameter"); Consumer<String> instanceLambda = (lambdaParameter) -> { System.out.println("effectivelyFinalMethodParameter is '" + effectivelyFinalMethodParameter + "'"); // Breakpoint 3 System.out.println("effectivelyFinal is '" + effectivelyFinal + "'"); System.out.println("lambdaParameter is '" + lambdaParameter + "'"); System.out.println("instanceField is '" + this.instanceField + "'"); }; instanceLambda.accept("Lambda Parameter"); } }
Moving to 4.7. Thanks Jesper for detailed analysis. I am not sure we want to do any assumption based on compiler implementation detail.
(In reply to Sarika Sinha from comment #3) > I am not sure we want to do any assumption based on compiler implementation > detail. We don't want to, but if there's no other choice, then we have to: - add workarounds (with fallbacks), and properly document the unsafe assumptions - file an enhancement request to get the necessary APIs added to JDI Since the OpenJDK bug tracker is effectively unusable, we should first capture our requirements in a public place like wiki.eclipse.org.
Will start by creating a wiki page to capture the requirements.
Created couple of requirements - https://wiki.eclipse.org/Debug/LambdaAndJDI
This bug is broken into two parts Bug 516278 and Bug 516319. *** This bug has been marked as a duplicate of bug 516278 ***