Update null pointer exception message to print out the method
Let's add the method in the logging string for context when debugging failures. This should help developers debug more quickly.
Bug: 217171086
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I1aadeaa536f58a22dccaf6f1c783df23c9430c7a
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index c6e7cfb..17a0a8a 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -23,6 +23,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "art_method.h"
#include "class_linker-inl.h"
#include "debug_print.h"
#include "dex/dex_file-inl.h"
@@ -406,10 +407,11 @@
// NullPointerException
-void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) {
+void ThrowNullPointerExceptionForFieldAccess(ArtField* field, ArtMethod* method, bool is_read) {
std::ostringstream msg;
- msg << "Attempt to " << (is_read ? "read from" : "write to")
- << " field '" << ArtField::PrettyField(field, true) << "' on a null object reference";
+ msg << "Attempt to " << (is_read ? "read from" : "write to") << " field '"
+ << ArtField::PrettyField(field) << "' on a null object reference in method '"
+ << ArtMethod::PrettyMethod(method) << "'";
ThrowException("Ljava/lang/NullPointerException;", nullptr, msg.str().c_str());
}
@@ -585,7 +587,7 @@
ArtField* field =
Runtime::Current()->GetClassLinker()->ResolveField(instr.VRegC_22c(), method, false);
Thread::Current()->ClearException(); // Resolution may fail, ignore.
- ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ true);
+ ThrowNullPointerExceptionForFieldAccess(field, method, /* is_read= */ true);
break;
}
case Instruction::IPUT:
@@ -598,7 +600,7 @@
ArtField* field = Runtime::Current()->GetClassLinker()->ResolveField(
instr.VRegC_22c(), method, /* is_static= */ false);
Thread::Current()->ClearException(); // Resolution may fail, ignore.
- ThrowNullPointerExceptionForFieldAccess(field, /* is_read= */ false);
+ ThrowNullPointerExceptionForFieldAccess(field, method, /* is_read= */ false);
break;
}
case Instruction::AGET:
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index 3a723f7..843c455 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -210,8 +210,7 @@
// NullPointerException
-void ThrowNullPointerExceptionForFieldAccess(ArtField* field,
- bool is_read)
+void ThrowNullPointerExceptionForFieldAccess(ArtField* field, ArtMethod* method, bool is_read)
REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
void ThrowNullPointerExceptionForMethodAccess(uint32_t method_idx,
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index 618f763..d32aa39 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -85,7 +85,7 @@
HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
- ThrowNullPointerExceptionForFieldAccess(field, (type & FindFieldFlags::ReadBit) != 0);
+ ThrowNullPointerExceptionForFieldAccess(field, referrer, (type & FindFieldFlags::ReadBit) != 0);
return nullptr;
}
return field;
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 95e3bd5..df18eeb 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -393,9 +393,9 @@
uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
- ArtField* f =
- FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
- Primitive::ComponentSize(field_type));
+ ArtMethod* method = shadow_frame.GetMethod();
+ ArtField* f = FindFieldFromCode<find_type, do_access_check>(
+ field_idx, method, self, Primitive::ComponentSize(field_type));
if (UNLIKELY(f == nullptr)) {
CHECK(self->IsExceptionPending());
return false;
@@ -413,7 +413,7 @@
} else {
obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
if (UNLIKELY(obj == nullptr)) {
- ThrowNullPointerExceptionForFieldAccess(f, true);
+ ThrowNullPointerExceptionForFieldAccess(f, method, true);
return false;
}
}
@@ -492,9 +492,9 @@
const bool do_assignability_check = do_access_check;
bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
- ArtField* f =
- FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
- Primitive::ComponentSize(field_type));
+ ArtMethod* method = shadow_frame.GetMethod();
+ ArtField* f = FindFieldFromCode<find_type, do_access_check>(
+ field_idx, method, self, Primitive::ComponentSize(field_type));
if (UNLIKELY(f == nullptr)) {
CHECK(self->IsExceptionPending());
return false;
@@ -505,7 +505,7 @@
} else {
obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
if (UNLIKELY(obj == nullptr)) {
- ThrowNullPointerExceptionForFieldAccess(f, false);
+ ThrowNullPointerExceptionForFieldAccess(f, method, false);
return false;
}
}
diff --git a/test/201-built-in-except-detail-messages/src/Main.java b/test/201-built-in-except-detail-messages/src/Main.java
index 9fc47f6..edc8baa 100644
--- a/test/201-built-in-except-detail-messages/src/Main.java
+++ b/test/201-built-in-except-detail-messages/src/Main.java
@@ -311,7 +311,9 @@
int i = a.i;
fail();
} catch (NullPointerException ex) {
- assertEquals("Attempt to read from field 'int A.i' on a null object reference", ex.getMessage());
+ assertEquals(
+ "Attempt to read from field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
+ ex.getMessage());
}
// Write field.
@@ -320,7 +322,9 @@
a.i = 1;
fail();
} catch (NullPointerException ex) {
- assertEquals("Attempt to write to field 'int A.i' on a null object reference", ex.getMessage());
+ assertEquals(
+ "Attempt to write to field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
+ ex.getMessage());
}
// Read array.