RFR(L): 8218628: Add detailed message to NullPointerException describing what is null.

Mandy Chung mandy.chung at oracle.com
Fri Mar 15 18:43:21 UTC 2019


That's a good suggestion.  The JDK out-of-the-box case and the
complex environment case with instrumentation agents transforming
the bytecodes are two different use cases.  This brings up one
issue that when constructing the enhanced NPE message, a method
might become obsolete due to redefintion, it should handle
gracefully.

Mandy

On 3/15/19 10:34 AM, Maurizio Cimadamore wrote:
> You touch an important point here - who is this feature for? Is it for 
> the casual developer in need of some hand holding? Or is it for 
> diagnosing complex instrumented stacks? I think the two use cases are 
> not necessarily similar and might be served by different sets of 
> enhancements. In the latter case it might be ok, for instance, to say 
> "and, btw, the NPE came from local[1]". But for users in the former 
> bucket (and most users, really), this level of detail will simply be 
> unacceptable (since now they have to understand the JVMS to parse the 
> message :-)).
> 
> I suggest we separate the use cases, at least for the purpose of the 
> design discussion.
> 
> Maurizio
> 
> On 15/03/2019 13:11, Lindenmaier, Goetz wrote:
>> Hi Maurizio,
>>
>> thanks for sharing your patch!  This is about what I thought about
>> so far, just that it's working already :)
>>
>> It prints the information of the failing bytecode.  Adding the dataflow
>> analysis, the other information could be printed as well.
>>
>> The major problem I see is here:
>> +            File f = new File(location.getFile(),
>> +                    clazz.getCanonicalName().replaceAll("\\.", "/") + 
>> ".class");
>> +            ClassReader cr = new ClassReader(new FileInputStream(f));
>> +            ClassNode classNode = new ClassNode();
>> +            cr.accept(classNode, 0);
>>
>> As I understand, this reads the Bytecode from the classfile.
>> The bytecode in the classfile must not match that executed
>> by the VM, i.e, the pc you get from the stackWalker will not
>> reference the bytecode that caused the NPE.
>>
>> Other issues have been discussed in the mail thread before.
>> Good that you point this out, I'll add it to the JEP.
>>
>> Best regards,
>>    Goetz
>>
>> ... Sorry, I missed the "reply all" on my first reply.
>>
>>
>>
>>
>>> -----Original Message-----
>>> From: Maurizio Cimadamore <maurizio.cimadamore at oracle.com>
>>> Sent: Freitag, 15. März 2019 12:33
>>> To: Lindenmaier, Goetz <goetz.lindenmaier at sap.com>; Mandy Chung
>>> <mandy.chung at oracle.com>; Roger Riggs <Roger.Riggs at oracle.com>
>>> Cc: Java Core Libs <core-libs-dev at openjdk.java.net>; hotspot-runtime-
>>> dev at openjdk.java.net
>>> Subject: Re: RFR(L): 8218628: Add detailed message to 
>>> NullPointerException
>>> describing what is null.
>>>
>>> Hi Goetz,
>>> please find the attached ASM-based patch. It is just a PoC, as such it
>>> does not provide as fine-grained messages as the one discussed in the
>>> RFE/JEP, but can be enhanced to cover custom debugging attribute, I 
>>> believe.
>>>
>>> When running this:
>>>
>>> Object o = null;
>>> o.toString();
>>>
>>> you get:
>>>
>>> Exception in thread "main" java.lang.NullPointerException: attempt to
>>> dereference 'null' when calling method 'toString'
>>>       at org.oracle.npe.NPEHandler.main(NPEHandler.java:103)
>>>
>>> While when running this:
>>>
>>> Foo foo = null;
>>> int y = foo.x;
>>>
>>> You get this:
>>>
>>> Exception in thread "main" java.lang.NullPointerException: attempt to
>>> dereference 'null' when accessing field 'x'
>>>       at org.oracle.npe.NPEHandler.main(NPEHandler.java:105)
>>>
>>> One problem I had is that ASM provides no way to get the instruction
>>> given a program counter - which means we have to scan all the bytecodes
>>> and update the sizes as we go along, and, ASM unfortunately doesn’t
>>> expose opcode sizes either. A more robust solution would be to have a
>>> big switch which returned the opcode size of any given opcode. Also,
>>> accessing to StackWalker API on exception creation might not be
>>> desirable in terms of performances, so this might be one of these area
>>> where some VM help could be beneficial. Another problem is that we
>>> cannot distinguish between user-generated exceptions (e.g. `throw new
>>> NullPointerException`) and genuine NPE issued by the VM.
>>>
>>> But I guess the upshot is that it works to leave all the gory detail of
>>> bytecode grovelling to a bytecode API - if the logic is applied lazily,
>>> then the impact on performances should be minimal, and the solution more
>>> maintainable longer term.
>>>
>>> Cheers
>>> Maurizio
>>>
>>> On 15/03/2019 07:59, Lindenmaier, Goetz wrote:
>>>> Yes, it would be nice if you shared that.


More information about the core-libs-dev mailing list