OSDN Git Service

Fix reference leaks in ToReflectedMethod and ToReflectedField
authorMathieu Chartier <mathieuc@google.com>
Sat, 15 Nov 2014 21:07:39 +0000 (13:07 -0800)
committerMathieu Chartier <mathieuc@google.com>
Mon, 17 Nov 2014 18:05:04 +0000 (10:05 -0800)
Used ScopedLocalRef to fix, added regression tests.

Bug: 18396311
Change-Id: I8ef447408f103c35389e76c14071a0f2e40de300

runtime/jni_internal.cc
runtime/jni_internal_test.cc

index bdda5c8..c11396f 100644 (file)
@@ -622,7 +622,7 @@ class JNI {
     ScopedObjectAccess soa(env);
     mirror::ArtMethod* m = soa.DecodeMethod(mid);
     CHECK(!kMovingMethods);
-    jobject art_method = soa.AddLocalReference<jobject>(m);
+    ScopedLocalRef<jobject> art_method(env, soa.AddLocalReference<jobject>(m));
     jobject reflect_method;
     if (m->IsConstructor()) {
       reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
@@ -633,7 +633,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;
   }
 
@@ -641,13 +641,13 @@ class JNI {
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::ArtField* f = soa.DecodeField(fid);
-    jobject art_field = soa.AddLocalReference<jobject>(f);
+    ScopedLocalRef<jobject> art_field(env, soa.AddLocalReference<jobject>(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;
   }
 
index bb46321..8ae28cd 100644 (file)
@@ -376,6 +376,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.
@@ -407,6 +412,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.