Is it possible to track down which expression caused an NPE?

null pointer exception
jep 358
showcodedetailsinexceptionmessages
-xx:+showcodedetailsinexceptionmessages
how to avoid null pointer exception in java
elvis operator kotlin
how to handle null pointer exception in java 8

When I get an NPE, I'll get a stack trace with line number. That's helpful, but if the line is very dense and/or contains nested expression, it's still impossible to figure out which reference was null.

Surely, this information must've been available somewhere. Is there a way to figure this out? (If not java expression, then at least the bytecode instruction that caused NPE would be helpful as well)

Edit #1: I've seen a few comments suggesting breaking up the line, etc, which, no offence, is really non-constructive and irrelevant. If I could do that, I would have ! Let just say this modifying the source is out of the question.

Edit #2: apangin has posted an excellent answer below, which I accepted. But it's SOOO COOL that I had to include the output here for anyone who doesn't want to try it out themselves! ;)

So suppose I have this driver program TestNPE.java

 1  public class TestNPE {
 2      public static void main(String[] args) {
 3          int n = 0;
 4          String st = null;
 5  
 6          System.out.println("about to throw NPE");
 7          if (n >= 0 && st.isEmpty()){
 8              System.out.println("empty");
 9          }
10          else {
11              System.out.println("othereise");
12          }
13      }
14      
15  }

The bytecode looks like this (showing only the main() method and omitting other irrelevant parts)

Code:
  stack=2, locals=3, args_size=1
     0: iconst_0
     1: istore_1
     2: aconst_null
     3: astore_2
     4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;                                              
     7: ldc           #3                  // String about to throw NPE                                                                     
     9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V                                      
    12: iload_1
    13: iflt          34
    16: aload_2
    17: invokevirtual #5                  // Method java/lang/String.isEmpty:()Z                                                           
    20: ifeq          34
    23: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;                                              
    26: ldc           #6                  // String empty                                                                                  
    28: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V                                      
    31: goto          42
    34: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;                                              
    37: ldc           #7                  // String othereise                                                                              
    39: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V                                      
    42: return

Now when you run the TestNPE driver with the agent, you'll get this

$ java -agentpath:libRichNPE.o TestNPE
about to throw NPE
Exception in thread "main" java.lang.NullPointerException: location=17
    at TestNPE.main(TestNPE.java:7)

So that points to the invokevirtual #5 at offset 17! Just HOW COOL IS THAT?

When an exception happens, JVM knows the original bytecode that caused the exception. However, StackTraceElement does not track bytecode indices.

The solution is to capture bytecode index using JVMTI whenever exception occurs.

The following sample JVMTI agent will intercept all exceptions, and if exception type is NullPointerException, the agent will replace its detailMessage with the bytecode location information.

#include <jvmti.h>
#include <stdio.h>

static jclass NullPointerException;
static jfieldID detailMessage;

void JNICALL VMInit(jvmtiEnv* jvmti, JNIEnv* env, jthread thread) {
    jclass localNPE = env->FindClass("java/lang/NullPointerException");
    NullPointerException = (jclass) env->NewGlobalRef(localNPE);

    jclass Throwable = env->FindClass("java/lang/Throwable");
    detailMessage = env->GetFieldID(Throwable, "detailMessage", "Ljava/lang/String;");
}

void JNICALL ExceptionCallback(jvmtiEnv* jvmti, JNIEnv* env, jthread thread,
                               jmethodID method, jlocation location, jobject exception,
                               jmethodID catch_method, jlocation catch_location) {
    if (env->IsInstanceOf(exception, NullPointerException)) {
        char buf[32];
        sprintf(buf, "location=%ld", (long)location);
        env->SetObjectField(exception, detailMessage, env->NewStringUTF(buf));
    }
}

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    jvmtiEnv* jvmti;
    vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0);

    jvmtiCapabilities capabilities = {0};
    capabilities.can_generate_exception_events = 1;
    jvmti->AddCapabilities(&capabilities);

    jvmtiEventCallbacks callbacks = {0};
    callbacks.VMInit = VMInit;
    callbacks.Exception = ExceptionCallback;
    jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
    jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
    jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, NULL);

    return 0;
}

Compile this into a shared library and run java with -agentpath option:

java -agentpath:/pato/to/libRichNPE.so Main

JEP 358: Helpful NullPointerExceptions, It is not a goal to track down the ultimate producer of a null reference, only the unlucky consumer. The JVM will print out the method, filename, and line number that caused the NPE: In addition, when the expression involves an array access, the Any other bytecode, No NPE possible, no message� Is it possible to track down which expression caused an NPE? Java “Thread-2” without stack prevents termination ; Simplest way to catch JS errors ; What does $$ and<generated> means in java stacktrace? What's Dead & Exploded in Swift's exception stack?

The exception itself does not have enough information to provide more than line numbers.

One option i see is to use a bytecode debugger like bytecode visualizer to closer localize the bytecode instruction that causes the npe. Step forward until the exception occurs, or add a breakpoint for npe.

Java NullPointerException, The instanceof operator is NPE safe. So, instanceof null always returns false. It does not cause a NullPointerException. You can eliminate messy� The result will be a more accurate report of the null variable in the JVM's message, but reformatting code to track down an exception is undesirable. In any case, most NPEs occur in production environments, where the support engineer who observes the NPE is many steps removed from the developer whose code caused it.

JEP 358: Helpful NullPointerExceptions adds such a feature to OpenJDK 14. It is disabled by default; you have to specify -XX:+ShowCodeDetailsInExceptionMessages to enable it. With it, your example results in:

Exception in thread "main"
java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "st" is null
    at TestNPE.main(TestNPE.java:7)

Classes do not need to be recompiled to take advantage of this feature. It was originally developed for the SAP JVM.

Engineering NullAway, Uber's Open Source Tool for Detecting NPEs, Mobile crashes can cause significant problems for our users, such as preventing NPEs, which occur when a null pointer is dereferenced in Java, are a use static code analysis tools to prevent NPE crashes as much as possible. Figure 2: In three easy steps, NullAway determines if an expression “e” in� NPE-Free Code Without Null Checks Optionals provide a great way to avoid null checks. See how you can wrap your code with Optionals to handle values that might or might not be null.

The stack trace mechanism relies on the debugging metadata optionally compiled into each class (namely the SourceFile and LineNumberTable attributes). As far as I know, bytecode offsets are not preserved anywhere. However, these would not be useful for a typical Java program, since you still have know what code each bytecode instruction corresponds to.

However, there is an obvious workaround - just break the code in question up into multiple lines and recompile! You can insert whitespace almost anywhere in Java.

Null Safety, The only possible causes of NPE's may be: For example, a regular variable of type String can not hold null: If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the� Looking for online definition of NPE or what NPE stands for? NPE is listed in the World's largest and most authoritative dictionary database of abbreviations and acronyms The Free Dictionary

You can either break up the complex line into many smaller ones you can trace, or you use your debugger to see what value was null when the exception occurred.

While you could try to look at the byte code where this happened, this will only be the start of a complex journey. I suggest making your code simpler to understand and you might work out which values could be null (Note: it could be null unless you know it's not possible)

Better Default NullPointerException Messages Coming to Java , The description of this enhancement states, "When getting a NPE, it is often hard to determine which reference in an expression had been null. This complicates finding the cause of the exception. Andrew Dinn: "Also, if you want your message to reflect the bytecode that is actually in use when the� Question: How do I track down the cause of the NPE exception in my code? This is the hard part. The short answer is to apply logical inference to the evidence provided by the stack trace, the source code and the relevant API documentation.

Fix NPE in pushdown to NULL expression � Issue #3408 � prestosql , cla-signed. toImmutableList does not accept nulls, so pushdown to a null expression fails: Caused by: java.lang. Can you add a test that reproduces the issue? Question: How do I track down the cause of the NPE exception in my code? This is the hard part. The short answer is to apply logical inference to the evidence provided by the stack trace, the source code and the relevant API documentation.

Apache Tomcat 7 (7.0.105), 64191: Fix an SCI support regression that was caused by a JAR path lookup error in the Add a META-INF/services entry to jasper-el.jar so that the Expression Avoid a NullPointerException when a Context is defined in server. xml with a Java profiler for helping to track down the wasted memory and the root causes. What caused this=> I added a table and created a power query in excel. When I appended the query to my existing query, what it does is creates a new tab with it appended. The only problem is that I have the dataset source pointing to the table "master" and now I have a table that is called "appended1".

Identification of Neuronal Enhancers of the Proopiomelanocortin , Combining a functional expression analysis in transgenic mice together with in silico Information (NCBI) Trace database (http://www.ncbi.nih.gov/Traces/trace. cgi). Nevertheless, it is possible that each nPE enhancer plays a unique role in Total POMC deficiency causes a complicated syndrome that includes adrenal� And often, the lower the track you're on, the less you're expected to learn - and the less you're taught. Even if you have low grades or nobody in your family ever went to college, if you want to go to college, you should demand the type of education you need to realize your dreams.

Comments
  • Good question, but also keep in mind that if the line is dense the code quality is probably less than optimal.
  • I know you can't get the column number...but if you can use returns to break the calls on that line out to a series of lines Java will print the relevant row number while still treating it as a line.
  • It depends on the JVM implementation. For instance SAP JVM prints the field name which was null in the exception message.
  • Edit to add newlines.
  • @Svetlin Zarev: There is also a JEP openjdk.java.net/jeps/8220715 that contributes the functionality of SAPJVM to OpenJDK
  • Oh, this is interesting! Thanks. I'll give that a try.
  • @apngin: Sorry, how do I compile this into a shared library?
  • I've got the following error while trying to compile it paste.ubuntu.com/23339517
  • @OneTwoThree This is C++ source. Try g++ -shared -fPIC -I/usr/java/jdk1.8.0_102/include -I/usr/java/jdk1.8.0_102/include/linux -o libRichNPE.so RichNPE.cpp
  • Oh, yes! It compiled! But when I ran it, I'm not seeing anything different: paste.ubuntu.com/23339661