Hiding the lambda proxy frame

Yuval Shavit yuval.shavit at gmail.com
Wed Jun 12 16:25:49 PDT 2013


There's some precedence here, in generics. Say I have:

    public interface Generic<T> {
        void foo(T arg);
    }

    public class Concrete implements Generic<String> {
        @Override
        public void foo(String arg) {
            System.out.println(arg.toString());
        }

        public static void main(String[] args) {
            Generic<String> o = new Concrete();
            o.foo(null);
        }
    }

    Exception in thread "main" java.lang.NullPointerException
        at Concrete.foo(Concrete.java:4)
        *at Concrete.foo(Concrete.java:1)   <-------------*
        at Concrete.main(Concrete.java:9)

The "Concrete.java:1" line for the generated raw method (I forget what this
is called) seems analogous to the lambda proxy. I could see this going two
ways: (1) show the proxy's frame, because there's precedent with generics;
or (2) hide the proxy's frame, if the consensus is that showing
the analogous frame for generics was a mistake. I would vote the latter,
for what it's worth. It used to just confuse me, until I learned what it
was; then it just annoyed me when I stepped into a generic method. I ignore
them when looking at stack traces, so it doesn't bother me much -- but I
wouldn't miss them if they were hidden.

For those who want to show the frame, has seeing the frame for the raw
method in a generic class ever been useful to you?


On Wed, Jun 12, 2013 at 6:10 PM, Remi Forax <forax at univ-mlv.fr> wrote:

> Hi Dan,
>
>
> On 06/12/2013 10:41 PM, Daniel Heidinga 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.
>>
>>
> yes, it's a compiler issue.
> I've reported the bug and I'm sure it will be fixed soon.
>
>
>
>> 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.
>>
>>
> First, the debuggers use JDI so will get the correct stack frame in the
> debugger.
>
> I propose to hide a very specific stack frame which carry no information,
> one reason to hide it is that having an "Unknown Source" in a stack trace
> troubles a lot of people,
> the other is as you said to not expose detail of implementation.
> This stack frame is the activation of a method which is generated so your
> debugger will not help you here,
> apart if you use an eclipse plugin that dumps the bytecode, there is no
> Java code corresponding to that specific stack frame.
>
>
>
>> 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.
>>
>>
> This annotation is only available if you generate code to mitigate that
> issue.
>
>
>
>> 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?
>>
>>
> Only for the stack frame which is accessible from Throwable, there no way
> to bypass the security using it.
>
>
>> --Dan
>>
>>
> Rémi
>
>
>
>> >
>> > 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-<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-observers mailing list