Hiding the lambda proxy frame

John Rose john.r.rose at oracle.com
Wed Jun 12 14:34:51 PDT 2013

On Jun 12, 2013, at 1:41 PM, Daniel Heidinga <Daniel_Heidinga at ca.ibm.com> wrote:

> The more pressing concern from the presentation is whether the source file and line number for the lambda is correct.  Ensuring we get this right makes a lot of sense.  


(For debugging, I also like the idea of giving meaningful names to lambda bodies, when possible.)

A stacktrace is a powerful tool for debugging and allowing frames to be hidden decreases the value of the stacktrace.  With this behaviour change, the stacktrace and debugger will disagree on what the stack looks like - which is needlessly confusing.  Personally, I hate having my debugging tools lie to me so I'd rather see accurate stacktraces.


Here's an alternative to consider which involves fewer "lies":  Introduce tail calls and use them in adapter code generated for lambdas.  Then there's no confusion about the state of the JVM stack, since it is an operational change that all components would see in the same way.  There would be the usual confusion with tail calls, about "how did I get here?"

Tail calls are weaker than hiding.  In particular, if you need to apply a checkcast to the result of a call before returning from an adapter, then that adapter should (arguably) show up on the stack, since it still has work to do.

BTW, JDK 1.5 bridge methods (another kind of adapter code) have a similar issue with stack traces, and could also benefit from hiding and/or tail calling.

> An annotation that hides stack frames is too easy to abuse, even if you have the best of intentions (like hiding implementation details).  It will be over-used and lead to significant difficulties in finding where errors occurred.

That is true.  That is why @Hidden is non-public.

> How hidden are LambdaForms$Hidden frames?  Are they only hidden from stacktraces or do APIs like sun.reflect.Reflection.getCallerClass() also skip these hidden frames?

The Hidden annotation affects the behavior of Throwable.fillInStackTrace and nothing else.

— John

> --Dan
> > 
> > On 06/11/2013 03:22 PM, Brian Goetz wrote:
> > > Why wouldn't you bring this to the EG list instead?
> > 
> > Sure, it was an implementation detail for me, hence the post on lambda-dev.
> > 
> > So from lambda-dev:
> > Currently when you print a stacktrace that show a call inside a lambda,
> > users can see the the frame corresponding to the method of the generated
> > proxy.
> > 
> > By example:
> > java.lang.Throwable
> >        StackTraceTest.lambda$0(StackTraceTest.java:6)
> >        StackTraceTest$$Lambda$1.run(Unknown Source)     <--- ugly, isn't it
> >        StackTraceTest.main(StackTraceTest.java:8)
> > 
> > I think this line should not be visible to user, it doesn't provide 
> > useful information,
> > just make the stack trace longer than it should.
> > 
> > There is an annotation LambdaForm.Hidden that you can use to mark method
> > that should be hidden when dumping the stack trace.
> > (Maybe the annotation should be a top-level by the way, add John in CC given
> > he is the creator of this annotation)
> > 
> > This part was not in the original mail:
> > Moreover, offline, one of my friend point me to a presentation of Jamie 
> > Allen
> > http://jaxenter.com/what-you-need-to-know-about-lambdas-by-jamie-
> > allen-47356.html
> > on the same subject at JAXConf 2013. I've just finished to see it.
> > 
> > He raises a good point that the compiler translation should try to 
> > provide a better name.
> > By example,
> >    Runnable myRunnable = () -> System.out.println("hello");
> > should result in a lambda that instead to be called "lambda$0",
> > instead the compiler should try to name it something like lambda$myRunnable
> > (or lambda$myRunnable0, ..., if there is a collision) if it's possible.
> > 
> > I think we already discuss about something like that in the light of 
> > serialization,
> > but not in the stack trace context.
> > 
> > Rémi
> > 
> > 

More information about the lambda-spec-experts mailing list