summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Santiago Aboy Solanes <solanes@google.com> 2022-02-04 14:15:01 +0000
committer Treehugger Robot <treehugger-gerrit@google.com> 2022-02-18 11:06:25 +0000
commit14e8d6429839c58f873f6fdfc5663151aa803b37 (patch)
tree105619787c7747818650085669035f34a6ea36a7
parent5171813632baff231dc2a9b0e794a13c908ab344 (diff)
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
-rw-r--r--runtime/common_throws.cc12
-rw-r--r--runtime/common_throws.h3
-rw-r--r--runtime/entrypoints/quick/quick_field_entrypoints.cc2
-rw-r--r--runtime/interpreter/interpreter_common.h16
-rw-r--r--test/201-built-in-except-detail-messages/src/Main.java8
5 files changed, 23 insertions, 18 deletions
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index c6e7cfb5ae..17a0a8a714 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 @@ void ThrowNoSuchMethodError(InvokeType type,
// 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 @@ void ThrowNullPointerExceptionFromDexPC(bool check_address, uintptr_t addr) {
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 @@ void ThrowNullPointerExceptionFromDexPC(bool check_address, uintptr_t addr) {
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 3a723f7f5a..843c455878 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -210,8 +210,7 @@ void ThrowNoSuchMethodError(InvokeType type,
// 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 618f7636da..d32aa39996 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -85,7 +85,7 @@ ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
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 95e3bd521e..df18eeb124 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -393,9 +393,9 @@ ALWAYS_INLINE bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Ins
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 @@ ALWAYS_INLINE bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Ins
} 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 @@ ALWAYS_INLINE bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
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 @@ ALWAYS_INLINE bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
} 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 9fc47f6409..edc8baab31 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 @@ public class Main {
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 @@ public class Main {
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.