diff options
Diffstat (limited to 'runtime/jni/check_jni.cc')
-rw-r--r-- | runtime/jni/check_jni.cc | 25 |
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); |