< prev index next >

src/hotspot/share/prims/jvm.cpp

Print this page
rev 56222 : 8218628: Add detailed message to NullPointerException describing what is null.
Summary: This is the implementation of JEP 358: Helpful NullPointerExceptions.
Reviewed-by: coleenp

@@ -36,10 +36,11 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "interpreter/bytecode.hpp"
+#include "interpreter/bytecodeUtils.hpp"
 #include "jfr/jfrEvents.hpp"
 #include "logging/log.hpp"
 #include "memory/heapShared.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/referenceType.hpp"

@@ -529,17 +530,64 @@
 
 
 
 // java.lang.Throwable //////////////////////////////////////////////////////
 
-
 JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver))
   JVMWrapper("JVM_FillInStackTrace");
   Handle exception(thread, JNIHandles::resolve_non_null(receiver));
   java_lang_Throwable::fill_in_stack_trace(exception);
 JVM_END
 
+// java.lang.NullPointerException ///////////////////////////////////////////
+
+// Replaces the following well-known class names:
+//   java.lang.Object -> Object
+//   java.lang.String -> String
+static void trim_well_known_class_names(char *message) {
+  size_t len = strlen(message);
+  size_t skip_len = strlen("java.lang.");
+  size_t min_pattern_len = strlen("java.lang.String");
+  if (len < min_pattern_len) return;
+
+  for (size_t isrc = 0, idst = 0; isrc <= len; isrc++, idst++) {
+    if (strncmp(message + isrc, "java.lang.Object", min_pattern_len) == 0 ||
+        strncmp(message + isrc, "java.lang.String", min_pattern_len) == 0   ) {
+      isrc += skip_len;
+    }
+    if (idst != isrc) {
+      message[idst] = message[isrc];
+    }
+  }
+}
+
+JVM_ENTRY(jstring, JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable))
+  if (!ShowCodeDetailsInExceptionMessages) return NULL;
+
+  oop exc = JNIHandles::resolve_non_null(throwable);
+
+  Method* method;
+  int bci;
+  if (!java_lang_Throwable::get_method_and_bci(exc, &method, &bci)) {
+    return NULL;
+  }
+  if (method->is_native()) {
+    return NULL;
+  }
+
+  ResourceMark rm(THREAD);
+  stringStream ss;
+  bool ok = BytecodeUtils::get_NPE_message_at(&ss, method, bci);
+  if (ok) {
+    char *result_string = ss.as_string();
+    trim_well_known_class_names(result_string);
+    oop result = java_lang_String::create_oop_from_str(result_string, CHECK_0);
+    return (jstring) JNIHandles::make_local(env, result);
+  } else {
+    return NULL;
+  }
+JVM_END
 
 // java.lang.StackTraceElement //////////////////////////////////////////////
 
 
 JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable))
< prev index next >