summaryrefslogtreecommitdiffstats
path: root/runtime/jni_internal.cc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-06-26 10:47:08 -0700
committerMathieu Chartier <mathieuc@google.com>2015-06-26 13:34:28 -0700
commite290896bfccb170f589407c0d10945c8ae0c5807 (patch)
tree8fb55a86919bf91547e56cc68bb01366dd03082d /runtime/jni_internal.cc
parent6415013f0b9509fed8367871daaf66c6841223f1 (diff)
downloadart-e290896bfccb170f589407c0d10945c8ae0c5807.tar.gz
art-e290896bfccb170f589407c0d10945c8ae0c5807.tar.bz2
art-e290896bfccb170f589407c0d10945c8ae0c5807.zip
Require mutator lock for DeleteLocalRef
There was a race condition where suspended threads could call DeleteLocalRef while the GC was marking their roots. This could cause the GC to attempt to mark a null object. (cherry picked from commit dd06afecd67fc6a60856436ab150a4d1b9a8ad29) Bug: 22119403 Change-Id: I962c717bb87b2acb2a4710a2d7ab16793e031401
Diffstat (limited to 'runtime/jni_internal.cc')
-rw-r--r--runtime/jni_internal.cc13
1 files changed, 7 insertions, 6 deletions
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 6ab44551d0..0a01f78fcb 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -554,15 +554,16 @@ class JNI {
return soa.AddLocalReference<jobject>(decoded_obj);
}
- static void DeleteLocalRef(JNIEnv* env, jobject obj)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ static void DeleteLocalRef(JNIEnv* env, jobject obj) {
if (obj == nullptr) {
return;
}
- IndirectReferenceTable& locals = reinterpret_cast<JNIEnvExt*>(env)->locals;
-
- uint32_t cookie = reinterpret_cast<JNIEnvExt*>(env)->local_ref_cookie;
- if (!locals.Remove(cookie, obj)) {
+ // SOA is only necessary to have exclusion between GC root marking and removing.
+ // We don't want to have the GC attempt to mark a null root if we just removed
+ // it. b/22119403
+ ScopedObjectAccess soa(env);
+ auto* ext_env = down_cast<JNIEnvExt*>(env);
+ if (!ext_env->locals.Remove(ext_env->local_ref_cookie, obj)) {
// Attempting to delete a local reference that is not in the
// topmost local reference frame is a no-op. DeleteLocalRef returns
// void and doesn't throw any exceptions, but we should probably