summaryrefslogtreecommitdiff
path: root/runtime/jni/check_jni.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/jni/check_jni.cc')
-rw-r--r--runtime/jni/check_jni.cc25
1 files changed, 17 insertions, 8 deletions
diff --git a/runtime/jni/check_jni.cc b/runtime/jni/check_jni.cc
index 5f0e468a93..eb54f9897f 100644
--- a/runtime/jni/check_jni.cc
+++ b/runtime/jni/check_jni.cc
@@ -38,6 +38,7 @@
#include "indirect_reference_table-inl.h"
#include "java_vm_ext.h"
#include "jni_internal.h"
+#include "local_reference_table-inl.h"
#include "mirror/class-inl.h"
#include "mirror/field.h"
#include "mirror/method.h"
@@ -57,14 +58,19 @@ namespace art {
inline IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
IndirectRefKind kind) {
DCHECK_NE(kind, kJniTransition);
- JNIEnvExt* env = soa.Env();
- IndirectReferenceTable* irt =
- (kind == kLocal) ? &env->locals_
- : ((kind == kGlobal) ? &env->vm_->globals_ : &env->vm_->weak_globals_);
+ DCHECK_NE(kind, kLocal);
+ JavaVMExt* vm = soa.Env()->GetVm();
+ IndirectReferenceTable* irt = (kind == kGlobal) ? &vm->globals_ : &vm->weak_globals_;
DCHECK_EQ(irt->GetKind(), kind);
return irt;
}
+// This helper cannot be in the anonymous namespace because it needs to be
+// declared as a friend by JniEnvExt.
+inline jni::LocalReferenceTable* GetLocalReferenceTable(ScopedObjectAccess& soa) {
+ return &soa.Env()->locals_;
+}
+
namespace {
using android::base::StringAppendF;
@@ -873,6 +879,12 @@ class ScopedCheck {
} else {
obj = soa.Decode<mirror::Object>(java_object);
}
+ } else if (ref_kind == kLocal) {
+ jni::LocalReferenceTable* lrt = GetLocalReferenceTable(soa);
+ okay = lrt->IsValidReference(java_object, &error_msg);
+ if (okay) {
+ obj = lrt->Get(ref);
+ }
} else {
IndirectReferenceTable* irt = GetIndirectReferenceTable(soa, ref_kind);
okay = irt->IsValidReference(java_object, &error_msg);
@@ -881,10 +893,7 @@ class ScopedCheck {
// Note: The `IsValidReference()` checks for null but we do not prevent races,
// so the null check below can still fail. Even if it succeeds, another thread
// could delete the global or weak global before it's used by JNI.
- if (ref_kind == kLocal) {
- // Local references do not need a read barrier.
- obj = irt->Get<kWithoutReadBarrier>(ref);
- } else if (ref_kind == kGlobal) {
+ if (ref_kind == kGlobal) {
obj = soa.Env()->GetVm()->DecodeGlobal(ref);
} else {
obj = soa.Env()->GetVm()->DecodeWeakGlobal(soa.Self(), ref);