JDK-8287533 : Always record hidden frames in backtrace to improve helpfull NPEs
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 19
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2022-05-30
  • Updated: 2024-01-11
  • Resolved: 2024-01-11
Related Reports
Relates :  
Description
Currently, when a NullPointerException is happening in a hidden frame, the Helpful NullPointerException from JEP 358 won't show any helpful information at all. 

This is because we are running with -XX:-ShowHiddenFrames by default and this setting disables the recording of the offending NPE method and BCI. Without this information the Helpful NullPointerException feature has no chance to display additional information about the NPE.

Consider the following trivial example from https://twitter.com/tagir_valeev/status/1530544950256992256

import java.util.*;

public class Demo {
  public static void main(String[] args) {
    List<String> input = Arrays.asList(null, " a ", " b ");
    List<String> list = input. stream().map(String::trim).toList();
  }
}

By default we get:

$ java Demo
Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
	at Demo.main(Demo.java:7)

And only with -XX:+ShowHiddenFrames we get the much more helpfull:

$ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames Demo
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.trim()" because "<parameter1>" is null
	at Demo$$Lambda$1/0x0000000801000a00.apply(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
	at Demo.main(Demo.java:7)

We should consider to always record hidden frames in the backtrace constructed by java_lang_Throwable::fill_in_stack_trace() (or at least for the top frame if it is hidden) and only filter out the hidden frames later on when the actual stack trace is built in java_lang_Throwable::get_stack_trace_elements(). This will help the Helpful NullPointerException feature to be more helpful :)

Comments
Runtime Triage: This is not on our current list of priorities. We will consider this feature if we receive additional customer requirements.
11-01-2024