ADDITIONAL SYSTEM INFORMATION :
OS X Mojave, openjdk 11/12/13
A DESCRIPTION OF THE PROBLEM :
JShell Eval translateExceptionStack uses a dangerous string comparison: `r.getFileName().equals("<none>")`.
StackTraceElement.getFileName javadoc states that it may return "...{@code null} if this information is unavailable."
Therefore, it is important that the constant "none" is on the left side of the `equals` invocation.
Additionally, it would be nice if the `JShellToolProvider.run` either re-throws the caught `ex`, or at least prints the stack trace. Most exceptions have helpful messages but it is often very helpful to have the stack trace as well. Consuming the exception with no opportunity to print the stack trace made diagnosing this issue more difficult.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In JShell, throw an exception where at least one frame is a Proxy invocation (or other source-less frame)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The `jshell` session prints the originally thrown exception and stack trace
ACTUAL -
java.lang.NullPointerException
at jdk.jshell/jdk.jshell.Eval.translateExceptionStack(Eval.java:1098)
at jdk.jshell/jdk.jshell.Eval.asEvalException(Eval.java:896)
at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:855)
at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140)
at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:493)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3547)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1301)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1203)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:1176)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.startUpRun(JShellTool.java:1143)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.resetState(JShellTool.java:1099)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.start(JShellTool.java:933)
at jdk.jshell/jdk.internal.jshell.tool.JShellToolBuilder.start(JShellToolBuilder.java:254)
at jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider.run(JShellToolProvider.java:94)
at JshellNpe.main(JshellNpe.java:20)
---------- BEGIN SOURCE ----------
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
import javax.tools.Tool;
public class JshellNpe {
public static void main(String... args) throws Exception {
final var shellStart = Files.createTempFile("init", "jsh");
Files.writeString(shellStart, String.format("%s.init();", JshellNpe.class.getName()));
shellStart.toFile().deleteOnExit();
ServiceLoader.load(Tool.class).stream()
.map(Provider::get)
.filter(t -> t.name().equals("jshell"))
.findAny()
.orElseThrow()
.run(System.in, System.out, System.err, new String[] {
"--startup", shellStart.toString(),
"--class-path", System.getProperty("java.class.path")});
}
public static void init() {
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] {},
(p, m, a) -> { throw new IllegalStateException("This helpful exception message is lost"); })
.hashCode();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Attach a debugger and breakpoint on exception to diagnose. Very unpleasant!
FREQUENCY : always
OS X Mojave, openjdk 11/12/13
A DESCRIPTION OF THE PROBLEM :
JShell Eval translateExceptionStack uses a dangerous string comparison: `r.getFileName().equals("<none>")`.
StackTraceElement.getFileName javadoc states that it may return "...{@code null} if this information is unavailable."
Therefore, it is important that the constant "none" is on the left side of the `equals` invocation.
Additionally, it would be nice if the `JShellToolProvider.run` either re-throws the caught `ex`, or at least prints the stack trace. Most exceptions have helpful messages but it is often very helpful to have the stack trace as well. Consuming the exception with no opportunity to print the stack trace made diagnosing this issue more difficult.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In JShell, throw an exception where at least one frame is a Proxy invocation (or other source-less frame)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The `jshell` session prints the originally thrown exception and stack trace
ACTUAL -
java.lang.NullPointerException
at jdk.jshell/jdk.jshell.Eval.translateExceptionStack(Eval.java:1098)
at jdk.jshell/jdk.jshell.Eval.asEvalException(Eval.java:896)
at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:855)
at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140)
at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:493)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3547)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1301)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1203)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:1176)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.startUpRun(JShellTool.java:1143)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.resetState(JShellTool.java:1099)
at jdk.jshell/jdk.internal.jshell.tool.JShellTool.start(JShellTool.java:933)
at jdk.jshell/jdk.internal.jshell.tool.JShellToolBuilder.start(JShellToolBuilder.java:254)
at jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider.run(JShellToolProvider.java:94)
at JshellNpe.main(JshellNpe.java:20)
---------- BEGIN SOURCE ----------
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
import javax.tools.Tool;
public class JshellNpe {
public static void main(String... args) throws Exception {
final var shellStart = Files.createTempFile("init", "jsh");
Files.writeString(shellStart, String.format("%s.init();", JshellNpe.class.getName()));
shellStart.toFile().deleteOnExit();
ServiceLoader.load(Tool.class).stream()
.map(Provider::get)
.filter(t -> t.name().equals("jshell"))
.findAny()
.orElseThrow()
.run(System.in, System.out, System.err, new String[] {
"--startup", shellStart.toString(),
"--class-path", System.getProperty("java.class.path")});
}
public static void init() {
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] {},
(p, m, a) -> { throw new IllegalStateException("This helpful exception message is lost"); })
.hashCode();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Attach a debugger and breakpoint on exception to diagnose. Very unpleasant!
FREQUENCY : always
- duplicates
-
JDK-8210527 JShell: NullPointerException in jdk.jshell.Eval.translateExceptionStack
- Resolved