< 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 >