Tuesday, 13 January 2015

What's Stopping Me Using Java8 Lambdas - Try Debugging Them

I'm a great fan of Java 8 features!  The declarative code style whilst possibly expensive in some cases is a massive leap forward for Java.

But - I'm still hesitant to use Java8 lambdas because it's so difficult to debug them!  See the screenshot below, which is currently at the breakpoint on line 18:


Notice how you only have visibility of the variables inside the lambda.  It is not even possible to see view the contents of the List 'letters' around which you are iterating.

Clearly in this contrived example it makes little difference but when you are debugging a complex system this becomes a serious pain in the neck.  Time and again I've found myself replacing lambda constructs for the old style loops so that I can see what's going on in variables outside the scope of the lambda.

I'm not sure if this problem is confined to IntelliJ or whether it exists in Eclipse, Netbeans etc [EDIT from the response from IntelliJ it seems to be a Java issue not an IntelliJ one] but IntelliJ is so great and I'm certainly not moving away from it in the near future.


I've raised this with the guys at IntelliJ and they have promised that someone will be looking into this problem.  I'll be updating this post with any progress.

[EDIT] UPDATE FROM INTELLIJ

You are welcome vote for it or star it to receive notifications about the future changes.

Unfortunately, it is not something we can do on our own, we’re waiting for JDK to support lambdas in the debugger.
Here’s the corresponding request in JDK tracker: https://bugs.openjdk.java.net/browse/JDK-8054220.

6 comments:

  1. Let me explain exactly what the issue is as there seems to have been a bit of confusion about my intentions on some discussion sites that have been discussing this post.

    I understand that by stepping into the lambda we are effectively stepping into a new frame analogous to 'stepping into a method' - therefore variables outside the frame will not be visible inside that frame.
    But - if we are stepping into a for loop of sorts (or perhaps the lines() method of Files) - you do want to see the other variables in the enclosing method. And the point is that using the old constructs this is exactly what you were able to do.

    Java is not functional enough (or at least the way I code isn't) that all the variables I need will be enclosed in the lambda.

    In fact when you step into a lambda you retain the scope of the enclosing class (unlike an inner class), so for example when you call toString() you will be printing the toString() of the enclosing object. For this reason it makes sense that in the debugger you should not be considered to have stepped into a new frame when you drop into a lambda.

    Ultimately this is all about usability and in real life I have found it extremely frustrating that I can't easily observe the values outside the lambda.

    ReplyDelete
  2. Can you not just switch to the outer stack frame during debugging? I work in C#, this is very simple there. Just a double-click on the appropriate stack frame in the Call Stack debug window, and you can inspect anything in the outer scope. OTOH, putting everything into the lambda's closure is inefficient. In your example the lambda did not close over anything from the outer scope, and can be compiled as a static method, making the code faster.

    ReplyDelete
  3. Yes this is possible (see my last comment). One of the best features now in IntelliJ 14 is the fact that all variable values in scope are actually overlaid on your code which is missed when you're in the lambda. What I'm saying is that we shouldn't have to sacrifice anything to move to a new style of coding and the reality is that I find myself reverting to non-lambda style code because of this feature.

    ReplyDelete
  4. Just a ping that https://bugs.openjdk.java.net/browse/JDK-8054220 was just fixed in JDK 9.

    ReplyDelete
  5. Isnt this obsolete with intellij supporting lambda debugging?

    ReplyDelete
    Replies
    1. It's great the IntellIJ supports Lambdas - but I think my point is still valid when you compare stepping into a lambda for loop as opposed to the normal way it's done. YOu still have to step up a frame to see your variable values. However tbh I've got used to it since writing this post.

      Delete