diff options
| -rw-r--r-- | runtime/indirect_reference_table-inl.h | 31 | ||||
| -rw-r--r-- | runtime/indirect_reference_table.cc | 32 | ||||
| -rw-r--r-- | runtime/indirect_reference_table.h | 5 |
3 files changed, 50 insertions, 18 deletions
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h index f70503d62a..5cc1de209d 100644 --- a/runtime/indirect_reference_table-inl.h +++ b/runtime/indirect_reference_table-inl.h @@ -36,21 +36,27 @@ inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { return false; } if (UNLIKELY(GetIndirectRefKind(iref) == kHandleScopeOrInvalid)) { - LOG(ERROR) << "JNI ERROR (app bug): invalid " << kind_ << " " << iref; - AbortIfNoCheckJNI(); + AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): invalid %s %p", + GetIndirectRefKindString(kind_), + iref)); return false; } const int topIndex = segment_state_.parts.topIndex; int idx = ExtractIndex(iref); if (UNLIKELY(idx >= topIndex)) { - LOG(ERROR) << "JNI ERROR (app bug): accessed stale " << kind_ << " " - << iref << " (index " << idx << " in a table of size " << topIndex << ")"; - AbortIfNoCheckJNI(); + std::string msg = StringPrintf( + "JNI ERROR (app bug): accessed stale %s %p (index %d in a table of size %d)", + GetIndirectRefKindString(kind_), + iref, + idx, + topIndex); + AbortIfNoCheckJNI(msg); return false; } if (UNLIKELY(table_[idx].GetReference()->IsNull())) { - LOG(ERROR) << "JNI ERROR (app bug): accessed deleted " << kind_ << " " << iref; - AbortIfNoCheckJNI(); + AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): accessed deleted %s %p", + GetIndirectRefKindString(kind_), + iref)); return false; } if (UNLIKELY(!CheckEntry("use", iref, idx))) { @@ -63,10 +69,13 @@ inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const { inline bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const { IndirectRef checkRef = ToIndirectRef(idx); if (UNLIKELY(checkRef != iref)) { - LOG(ERROR) << "JNI ERROR (app bug): attempt to " << what - << " stale " << kind_ << " " << iref - << " (should be " << checkRef << ")"; - AbortIfNoCheckJNI(); + std::string msg = StringPrintf( + "JNI ERROR (app bug): attempt to %s stale %s %p (should be %p)", + what, + GetIndirectRefKindString(kind_), + iref, + checkRef); + AbortIfNoCheckJNI(msg); return false; } return true; diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 8e49492cf4..f334a0553c 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -32,6 +32,20 @@ namespace art { static constexpr bool kDumpStackOnNonLocalReference = false; +const char* GetIndirectRefKindString(const IndirectRefKind& kind) { + switch (kind) { + case kHandleScopeOrInvalid: + return "HandleScopeOrInvalid"; + case kLocal: + return "Local"; + case kGlobal: + return "Global"; + case kWeakGlobal: + return "WeakGlobal"; + } + return "IndirectRefKind Error"; +} + template<typename T> class MutatorLockedDumpable { public: @@ -58,12 +72,14 @@ std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) return os; } -void IndirectReferenceTable::AbortIfNoCheckJNI() { +void IndirectReferenceTable::AbortIfNoCheckJNI(const std::string& msg) { // If -Xcheck:jni is on, it'll give a more detailed error before aborting. JavaVMExt* vm = Runtime::Current()->GetJavaVM(); if (!vm->IsCheckJniEnabled()) { // Otherwise, we want to abort rather than hand back a bad reference. - LOG(FATAL) << "JNI ERROR (app bug): see above."; + LOG(FATAL) << msg; + } else { + LOG(ERROR) << msg; } } @@ -113,9 +129,15 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); if (topIndex == max_entries_) { - LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " - << "(max=" << max_entries_ << ")\n" - << MutatorLockedDumpable<IndirectReferenceTable>(*this); + std::ostringstream oss; + oss << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")\n" + << MutatorLockedDumpable<IndirectReferenceTable>(*this); + if (VLOG_IS_ON(jni)) { + LOG(FATAL) << oss.str(); + } else { + LOG_FATAL_THIS_THREAD_ONLY(oss.str()); + } } // We know there's enough room in the table. Now we just need to find diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index 2d0ae63b22..4a671aa2d0 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -119,6 +119,7 @@ enum IndirectRefKind { kWeakGlobal = 3 // <<weak global reference>> }; std::ostream& operator<<(std::ostream& os, const IndirectRefKind& rhs); +const char* GetIndirectRefKindString(const IndirectRefKind& kind); /* * Determine what kind of indirect reference this is. @@ -372,8 +373,8 @@ class IndirectReferenceTable { return reinterpret_cast<IndirectRef>(uref); } - // Abort if check_jni is not enabled. - static void AbortIfNoCheckJNI(); + // Abort if check_jni is not enabled. Otherwise, just log as an error. + static void AbortIfNoCheckJNI(const std::string& msg); /* extra debugging checks */ bool GetChecked(IndirectRef) const; |