From 5a8964bd480a3307e4d5fa903b0c8c44bfa16048 Mon Sep 17 00:00:00 2001 From: ttyh061 Date: Tue, 16 Feb 2016 18:28:19 +0800 Subject: [PATCH] mobile/bind: fix JNI local reference table overflow The existing implementation has memory leaks on two local variables that are not deleted after use. Android app will crash after this issue. add UnitTest for this issue. Fixes golang/go#14346 Change-Id: Ic233d15556ac97b35e00e13279a572c48a03049f Reviewed-on: https://go-review.googlesource.com/19532 Reviewed-by: Elias Naur --- bind/java/SeqTest.java | 14 ++++++++++++-- bind/java/seq_android.c | 2 ++ bind/java/testpkg/testpkg.go | 10 ++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java index 5308bd8..381e6cb 100644 --- a/bind/java/SeqTest.java +++ b/bind/java/SeqTest.java @@ -4,10 +4,9 @@ package go; -import android.util.Log; -import android.test.suitebuilder.annotation.Suppress; import android.test.AndroidTestCase; import android.test.MoreAsserts; + import java.util.Arrays; import java.util.Random; @@ -386,6 +385,17 @@ public class SeqTest extends AndroidTestCase { assertEquals("want back the error message we set", want, got); } + //test if we have JNI local reference table overflow error + public void testLocalReferenceOverflow() { + Testpkg.CallWithCallback(new Testpkg.GoCallback.Stub() { + + @Override + public void VarUpdate() { + //do nothing + } + }); + } + public void testNullReferences() { assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest.Stub() { public Testpkg.NullTest Null() { diff --git a/bind/java/seq_android.c b/bind/java/seq_android.c index 4a72113..30839cb 100644 --- a/bind/java/seq_android.c +++ b/bind/java/seq_android.c @@ -262,12 +262,14 @@ void recv(int32_t ref, int code, uint8_t *in_ptr, size_t in_len, uint8_t **out_p memcpy(mem_write(env, in, in_len, 1), in_ptr, in_len); in_mem->off = 0; out = (*env)->CallStaticObjectMethod(env, seq_clazz, seq_recv, in, code, ref); + (*env)->DeleteLocalRef(env, in); if (out == NULL) { describe_exception(env); LOG_FATAL("failed to invoke Seq.recv"); return; } out_mem = mem_get(env, out); + (*env)->DeleteLocalRef(env, out); if (out_mem == NULL) { LOG_FATAL("recv on NULL out_mem"); return; diff --git a/bind/java/testpkg/testpkg.go b/bind/java/testpkg/testpkg.go index a2ec48f..862f201 100644 --- a/bind/java/testpkg/testpkg.go +++ b/bind/java/testpkg/testpkg.go @@ -220,6 +220,16 @@ func ReadAsset() string { return string(b) } +type GoCallback interface { + VarUpdate() +} + +func CallWithCallback(gcb GoCallback) { + for i := 0; i < 1000; i++ { + gcb.VarUpdate() + } +} + type NullTest interface { Null() NullTest }