Make it easier to recognize JNI reference bugs.
CheckJNI is still your best choice, but now, even without CheckJNI, you'll get
a strong clue:
E/dalvikvm( 4168): JNI ERROR (app bug): accessed stale local reference at index 10 (top=8)
E/dalvikvm( 4168): VM aborting
Change-Id: Ia65e1e430bc53509add19816ef06cc5dbd1b3e98
diff --git a/vm/IndirectRefTable.cpp b/vm/IndirectRefTable.cpp
index b8ae767..f2e7ca2 100644
--- a/vm/IndirectRefTable.cpp
+++ b/vm/IndirectRefTable.cpp
@@ -19,6 +19,14 @@
*/
#include "Dalvik.h"
+static void abortMaybe() {
+ // If CheckJNI is on, it'll give a more detailed error before aborting.
+ // Otherwise, we want to abort rather than hand back a bad reference.
+ if (!gDvmJni.useCheckJni) {
+ dvmAbort();
+ }
+}
+
bool IndirectRefTable::init(size_t initialCount,
size_t maxCount, IndirectRefKind desiredKind)
{
@@ -67,8 +75,9 @@
Object* obj = table[idx];
IndirectRef checkRef = toIndirectRef(obj, idx);
if (checkRef != iref) {
- LOGE("Attempt to use stale %s reference (req=%p vs cur=%p; table=%p)",
+ LOGE("JNI ERROR (app bug): use of stale %s reference (req=%p vs cur=%p; table=%p)",
indirectRefKindToString(kind), iref, checkRef, this);
+ abortMaybe();
return false;
}
return true;
@@ -89,9 +98,10 @@
if (topIndex == allocEntries) {
/* reached end of allocated space; did we hit buffer max? */
if (topIndex == maxEntries) {
- LOGW("%s reference table overflow (max=%d)",
+ LOGE("JNI ERROR (app bug): %s reference table overflow (max=%d)",
indirectRefKindToString(kind), maxEntries);
- return NULL;
+ dump(indirectRefKindToString(kind));
+ dvmAbort();
}
size_t newSize = allocEntries * 2;
@@ -102,14 +112,12 @@
Object** newTable = (Object**) realloc(table, newSize * sizeof(Object*));
if (newTable == NULL) {
- LOGE("Unable to expand %s reference table from %d to %d (max=%d)",
- indirectRefKindToString(kind), allocEntries,
- newSize, maxEntries);
- return NULL;
+ LOGE("JNI ERROR (app bug): unable to expand %s reference table (from %d to %d, max=%d)",
+ indirectRefKindToString(kind),
+ allocEntries, newSize, maxEntries);
+ dump(indirectRefKindToString(kind));
+ dvmAbort();
}
- LOGV("Growing %s reference table %p from %d to %d (max=%d)",
- indirectRefKindToString(kind), this,
- allocEntries, newSize, maxEntries);
/* update entries; adjust "nextEntry" in case memory moved */
table = newTable;
@@ -161,8 +169,9 @@
return false;
}
if (indirectRefKind(iref) == kIndirectKindInvalid) {
- LOGW("Invalid %s reference %p",
+ LOGE("JNI ERROR (app bug): invalid %s reference (%p)",
indirectRefKindToString(kind), iref);
+ abortMaybe();
return false;
}
@@ -170,15 +179,17 @@
int idx = extractIndex(iref);
if (idx >= topIndex) {
/* bad -- stale reference? */
- LOGW("Attempt to access stale %s reference at index %d (top=%d)",
- indirectRefKindToString(kind), idx, topIndex);
+ LOGE("JNI ERROR (app bug): accessed stale %s reference at index %d (top=%d)",
+ indirectRefKindToString(kind), idx, topIndex);
+ abortMaybe();
return false;
}
Object* obj = table[idx];
if (obj == NULL) {
- LOGW("Attempt to access deleted %s reference (%p)",
+ LOGE("JNI ERROR (app bug): use of deleted %s reference (%p)",
indirectRefKindToString(kind), iref);
+ abortMaybe();
return false;
}
if (!checkEntry(iref, idx)) {