/*
* Make sure that the entry at "idx" is correctly paired with "iref".
*/
-bool IndirectRefTable::checkEntry(IndirectRef iref, int idx) const
+bool IndirectRefTable::checkEntry(const char* what, IndirectRef iref, int idx) const
{
Object* obj = table[idx];
IndirectRef checkRef = toIndirectRef(obj, idx);
if (checkRef != iref) {
- LOGE("JNI ERROR (app bug): use of stale %s reference (req=%p vs cur=%p; table=%p)",
- indirectRefKindToString(kind), iref, checkRef, this);
- abortMaybe();
+ if (indirectRefKind(iref) != kIndirectKindWeakGlobal) {
+ LOGE("JNI ERROR (app bug): attempt to %s stale %s reference (req=%p vs cur=%p; table=%p)",
+ what, indirectRefKindToString(kind), iref, checkRef, this);
+ abortMaybe();
+ }
return false;
}
return true;
return false;
}
- Object* obj = table[idx];
- if (obj == NULL) {
- LOGE("JNI ERROR (app bug): use of deleted %s reference (%p)",
- indirectRefKindToString(kind), iref);
- abortMaybe();
- return false;
- }
- if (!checkEntry(iref, idx)) {
+ if (!checkEntry("use", iref, idx)) {
return false;
}
* required by JNI's DeleteLocalRef function.
*
* Note this is NOT called when a local frame is popped. This is only used
- * for explict single removals.
+ * for explicit single removals.
*
* Returns "false" if nothing was removed.
*/
* Top-most entry. Scan up and consume holes. No need to NULL
* out the entry, since the test vs. topIndex will catch it.
*/
- if (!checkEntry(iref, idx)) {
+ if (!checkEntry("remove", iref, idx)) {
return false;
}
updateSlotRemove(idx);
LOGV("--- WEIRD: removing null entry %d", idx);
return false;
}
- if (!checkEntry(iref, idx)) {
+ if (!checkEntry("remove", iref, idx)) {
return false;
}
updateSlotRemove(idx);
switch (indirectRefKind(jobj)) {
case kIndirectKindLocal:
- return getLocalRefTable(env)->get(jobj);
+ {
+ Object* result = getLocalRefTable(env)->get(jobj);
+ if (result == NULL) {
+ LOGE("JNI ERROR (app bug): use of deleted local reference (%p)", jobj);
+ dvmAbort();
+ }
+ return result;
+ }
case kIndirectKindGlobal:
{
// TODO: find a way to avoid the mutex activity here
IndirectRefTable* pRefTable = &gDvm.jniGlobalRefTable;
ScopedPthreadMutexLock lock(&gDvm.jniGlobalRefLock);
- return pRefTable->get(jobj);
+ Object* result = pRefTable->get(jobj);
+ if (result == NULL) {
+ LOGE("JNI ERROR (app bug): use of deleted global reference (%p)", jobj);
+ dvmAbort();
+ }
+ return result;
}
case kIndirectKindWeakGlobal:
{
- Object* result;
- {
- // TODO: find a way to avoid the mutex activity here
- IndirectRefTable* pRefTable = &gDvm.jniWeakGlobalRefTable;
- ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
- result = pRefTable->get(jobj);
- }
+ // TODO: find a way to avoid the mutex activity here
+ IndirectRefTable* pRefTable = &gDvm.jniWeakGlobalRefTable;
+ ScopedPthreadMutexLock lock(&gDvm.jniWeakGlobalRefLock);
+ Object* result = pRefTable->get(jobj);
+ // A cleared weak global reference means we might legitimately return NULL here.
/*
* TODO: this is a temporary workaround for broken weak global
- * refs (bug 4260055). We treat any invalid reference as if it
+ * refs (http://b/4260055). We treat any invalid reference as if it
* were a weak global with a cleared referent. This means that
* actual invalid references won't be detected, and if an empty
* slot gets re-used we will return the new reference instead.