From 41da59665556e8dd5601178185c68d48d645500b Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Sat, 15 Nov 2014 13:07:39 -0800 Subject: [PATCH] Fix reference leaks in ToReflectedMethod and ToReflectedField Used ScopedLocalRef to fix, added regression tests. Bug: 18396311 (cherry picked from commit 8c41753e5eda8322b4d992fe88855058f4c0c2e1) Change-Id: I0ddfc20ac2384c90ff18586242c1f1d9a6d6eb6d --- runtime/jni_internal.cc | 8 ++++---- runtime/jni_internal_test.cc | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 3b0656e4c..1dcfcabf9 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -360,7 +360,7 @@ class JNI { ScopedObjectAccess soa(env); mirror::ArtMethod* m = soa.DecodeMethod(mid); CHECK(!kMovingMethods); - jobject art_method = soa.AddLocalReference(m); + ScopedLocalRef art_method(env, soa.AddLocalReference(m)); jobject reflect_method; if (m->IsConstructor()) { reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor); @@ -371,7 +371,7 @@ class JNI { return nullptr; } SetObjectField(env, reflect_method, - WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod, art_method); + WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod, art_method.get()); return reflect_method; } @@ -379,13 +379,13 @@ class JNI { CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); mirror::ArtField* f = soa.DecodeField(fid); - jobject art_field = soa.AddLocalReference(f); + ScopedLocalRef art_field(env, soa.AddLocalReference(f)); jobject reflect_field = env->AllocObject(WellKnownClasses::java_lang_reflect_Field); if (env->ExceptionCheck()) { return nullptr; } SetObjectField(env, reflect_field, - WellKnownClasses::java_lang_reflect_Field_artField, art_field); + WellKnownClasses::java_lang_reflect_Field_artField, art_field.get()); return reflect_field; } diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index ccad13716..e5923deb6 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -799,6 +799,11 @@ TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) { ASSERT_NE(fid, nullptr); // Turn the fid into a java.lang.reflect.Field... jobject field = env_->ToReflectedField(c, fid, JNI_FALSE); + for (size_t i = 0; i <= 512; ++i) { + // Regression test for b/18396311, ToReflectedField leaking local refs causing a local + // reference table overflows with 512 references to ArtField + env_->DeleteLocalRef(env_->ToReflectedField(c, fid, JNI_FALSE)); + } ASSERT_NE(c, nullptr); ASSERT_TRUE(env_->IsInstanceOf(field, jlrField)); // ...and back again. @@ -825,6 +830,11 @@ TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) { ASSERT_NE(mid, nullptr); // Turn the mid into a java.lang.reflect.Constructor... jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE); + for (size_t i = 0; i <= 512; ++i) { + // Regression test for b/18396311, ToReflectedMethod leaking local refs causing a local + // reference table overflows with 512 references to ArtMethod + env_->DeleteLocalRef(env_->ToReflectedMethod(c, mid, JNI_FALSE)); + } ASSERT_NE(method, nullptr); ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor)); // ...and back again. -- 2.11.0