mgroovy created GROOVY-10258:
--------------------------------
Summary: NPE: Pinpoint Exact Location in Call Chain
Key: GROOVY-10258
URL: https://issues.apache.org/jira/browse/GROOVY-10258
Project: Groovy
Issue Type: Bug
Reporter: mgroovy
Groovy should output the exact location where a NullPointerException occurred
inside a call chain in the NPE message, if possible pretty printed.
The JVM has been improved in this regard since OpenJDK 14:
https://openjdk.java.net/jeps/358
https://www.baeldung.com/java-14-nullpointerexception
https://bugs.openjdk.java.net/browse/JDK-8233014
The messages produced alas look pretty ugly for @CompileStatic Groovy (see
below), due to its predominant use of properties instead of fields, and the
original goal of JEP 358 to print the complete call chain (access path) seems
to have been dropped, so it is not particularily helpful in some situations
(see examples below).
In Groovy 3.0.9 under OpenJDK 16:
{code}
@Newify(pattern=/[A-Z][A-Za-z0-9_]*/)
//@CompileStatic
class HelpfulNullPointerExceptionTest {
static class X {
X x; String s
X(X x, String s = null) { this.x = x; this.s = s }
@Override String toString() { "X($s,$x)" }
}
@Test
void nullPointerInCallChain() {
final x = X(X(X(X(null,"X-Men"))))
println "x.x.x.x=$x.x.x.x"
x.x.x = null
/*
* OpenJDK 16 (Eclipse jdk-16.0.2.7-hotspot) (Note:
-XX:+ShowCodeDetailsInExceptionMessages is now always on by default)
** @CompileDynamic: java.lang.NullPointerException: Cannot get
property 'x' on null object
** @CompileStatic: java.lang.NullPointerException: Cannot invoke
"simple.groovy.HelpfulNullPointerExceptionTest$X.getX()" because the return
value of "simple.groovy.HelpfulNullPointerExceptionTest$X.getX()" is null
** Would hope for something like (or its pretty-printed
equivalent): java.lang.NullPointerException: Cannot get property 'x.x.x.x' on
null object
*/
println "x.x.x.x=$x.x.x.x"
}
@Canonical static class A { String a }
@Canonical static class B { A a }
@Canonical static class C { B b }
@Canonical static class D { C c }
@Test
void nullPointerInCallChain2() {
final x = D(C(B(A("aha!"))))
println "x.c.b.a=$x.c.b.a"
/*
* OpenJDK 16 (Eclipse jdk-16.0.2.7-hotspot)
** @CompileDynamic: java.lang.NullPointerException: Cannot get
property 'b' on null object
** @CompileStatic: java.lang.NullPointerException: Cannot invoke
"simple.groovy.HelpfulNullPointerExceptionTest$C.getB()" because the return
value of "simple.groovy.HelpfulNullPointerExceptionTest$D.getC()" is null
** Would hope for something like (or its pretty-printed
equivalent): java.lang.NullPointerException: Cannot get property 'x.c.b.a' on
null object
*/
x.c = null
println "x.c.b.a=$x.c.b.a"
}
}
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)