RFR(L): 8218628: Add detailed message to NullPointerException describing what is null.
Roger Riggs
Roger.Riggs at oracle.com
Fri Feb 8 19:46:05 UTC 2019
Hi,
A few higher level issues should be considered, though the details of
the webrev
captured my immediate attention.
Is this the right feature and is this the right level of implementation
(C++/native)?
From a security perspective, adding field names to exceptions exposes
information to callers that they could not otherwise get and that breaks
encapsulation.
That needs to be evaluated.
I think there are ways to make this easier to implement and be easier to
maintain
and perform better.
NullPointerException:
28: unused import of Field
64: The lazyComputeMessage boolean should be inverted so it does not require
initialization, false is the default, anything else adds overhead.
And it may not be needed.
91: Why do you think synchonization is necessary? It is a performance hit.
It is highly unlikely to be called from multiple threads and the
value will
be the same whether it is computed once or multiple times by
different threads.
99: extendedMessage will never be null (so says the javadoc of
getExtendedNPEMessage)
Bug: If it does return null, then null is returned from getMessage
regardless of the value of super.getMessage().
121: Simplify getExtendedNPEMessage by making it only responsible for
the detail
and not concatenation with an existing message. Put that in
getMessage().
Its not strictly necessary to change the updated message with
setMessage().
Avoiding that will avoid complexity and a performance hit.
The message will be computed each time it is needed, and that happens
infrequently.
(Even in the serialization case, it will be re-computed from the
attached stack frames).
And it avoids adding setMessage() to Throwable, that's significant
change since
the current implementation only allows the message to be initialized
not updated.
Immutable is an important characteristic to maintain.
That makes the writeReplace() unnecessary too.
Additional command line arguments are an unnecessary complexity,
documentation, and maintenance overhead. If the feature is as valuable as
you suggest, it should be enabled all the time.
I'm assuming there are no tests broken by the modification of the message.
It is likely that somewhere an application or test looks at the message
itself.
Has that been verified?
I can't speak for the hotspot code, but that seems to add a lot of code
to support
only this convenience feature. That's a maintenance overhead and burden.
The change to the jtreg/vmTestbase/jit/t/t104/t104.gold file raises a
question
about how useful the information is, developers should not need to know
about "slot 1".
The test output of NullPointerExceptionTest shows
"java.lang.Object.hashCode(()I)".
Why is the argument type for Integer shown as "()I"; that's not the
conventional
representation of a primitive int.
Generally, the explanations are too verbose.
Method names and field names would be easier to recognize if they were
quoted, as is done with 'this'. Argument numbers should be digits,
not English words (first, second, etc) to make them easier to pick out.
And has it limits that do not read easily, e.g. "nr. 9".
I would not describe 'this' as a local variable.
Tests, especially new tests should compile without warnings.
NullPointerExceptionTest.java:125 newInstance has been deprecated.
The messages can be easier to understand, e.g.
'field a1 is null, trying to invoke a1.hashCode...' instead of:
"while trying to invoke the method java.lang.Object.hashCode(()I) on a
null reference loaded from local variable 'a1'"
It will easier to understand if it looks more like the code.
BTW, what does this look like for fully optimized code?
Does it bear any resemblance to the source code at all?
Or does it have to be deoptimized to come up with a sensible source
reference.
How much of this can be done in Java code with StackWalker and other
java APIs?
It would be a shame to add this much native code if there was a more robust
way to implement it using APIs with more leverage.
Regards, Roger
On 02/08/2019 09:13 AM, Langer, Christoph wrote:
> Hi Goetz,
>
>> ok, so here a new webrev just adding a setter for the field:
>> http://cr.openjdk.java.net/~goetz/wr19/8218628-exMsg-NPE/02
>>
>> ... and incorporating the other comments.
> Looks better
>
> I have a few additions to src/java.base/share/classes/java/lang/NullPointerException.java:
>
> 28 import java.lang.reflect.Field;
> 29
> -> can be removed now.
>
> 91 synchronized (this) {
> -> I think this is not needed here. The transient modifier for lazyComputeMessage already implies the lock on the Object, I think.
>
> 108 return extendedMessage;
> -> I guess it would be more correct if you returned super.getMessage() here.
>
> Thanks
> Christoph
More information about the core-libs-dev
mailing list