TBR v.io/x/jni: Delete local references when done with them

This *may* fix the syncslides crashes observed by afergan/kash.  We can't
reproduce the problem in a test, however, but that could be due to a
more generous (or infinite) ref limit on desktops.

Together with sjr@, who correctly observed that we're overflowing a
local reference table, not global.

Note that it's still unclear if we really hit a case with 154 glob
results, or it may be something else going on.  But this CL *is*
the right thing to do regardless.

Change-Id: I1250616818358760965495a03d3c972989a857ed
diff --git a/impl/google/namespace/jni.go b/impl/google/namespace/jni.go
index 5988465..2e19339 100644
--- a/impl/google/namespace/jni.go
+++ b/impl/google/namespace/jni.go
@@ -77,7 +77,7 @@
 		return jutil.NullObject, err
 	}
 
-	retChan := make(chan jutil.Object, 100)
+	retChan := make(chan jutil.Object, 5)
 	go func() {
 		env, freeFunc := jutil.GetEnv()
 		defer freeFunc()
@@ -97,6 +97,9 @@
 			// The other side of the channel is responsible for deleting this
 			// global reference.
 			retChan <- jutil.NewGlobalRef(env, jGlobReply)
+			// Free up the local reference as it'll be auto-freed only when
+			// freeFunc() gets executed, which can burn us for big globs.
+			jutil.DeleteLocalRef(env, jGlobReply)
 		}
 		close(retChan)
 	}()
diff --git a/util/jni_wrapper.c b/util/jni_wrapper.c
index ffdb0f7..21c4a74 100644
--- a/util/jni_wrapper.c
+++ b/util/jni_wrapper.c
@@ -154,12 +154,16 @@
   return (*env)->NewLocalRef(env, obj);
 }
 
+void DeleteLocalRef(JNIEnv* env, jobject localRef) {
+  (*env)->DeleteLocalRef(env, localRef);
+}
+
 jobject NewGlobalRef(JNIEnv* env, jobject obj) {
   return (*env)->NewGlobalRef(env, obj);
 }
 
 void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
-  return (*env)->DeleteGlobalRef(env, globalRef);
+  (*env)->DeleteGlobalRef(env, globalRef);
 }
 
 jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
diff --git a/util/jni_wrapper.h b/util/jni_wrapper.h
index 7093b1c..2241c30 100644
--- a/util/jni_wrapper.h
+++ b/util/jni_wrapper.h
@@ -106,6 +106,9 @@
 // Creates a new local reference to the object referred to by the obj argument.
 jobject NewLocalRef(JNIEnv* env, jobject obj);
 
+// Deletes the local reference pointed to by localRef.
+void DeleteLocalRef(JNIEnv* env, jobject localRef);
+
 // Creates a new global reference to the object referred to by the obj argument.
 jobject NewGlobalRef(JNIEnv* env, jobject obj);
 
diff --git a/util/ref.go b/util/ref.go
index 3efb7ae..2b19433 100644
--- a/util/ref.go
+++ b/util/ref.go
@@ -28,13 +28,18 @@
 	C.DeleteGlobalRef(env.value(), obj.value())
 }
 
-// Creates a new local reference that refers to the same object as obj. The
-// given obj may be a global or local reference. Returns null if ref refers
-// to null.
+// NewLocalRef creates a new local reference that refers to the same object
+// as obj. The given obj may be a global or local reference. Returns null if
+// ref refers to null.
 func NewLocalRef(env Env, obj Object) Object {
 	return Object(uintptr(unsafe.Pointer(C.NewLocalRef(env.value(), obj.value()))))
 }
 
+// DeleteLocalRef deletes the local reference pointed to by obj.
+func DeleteLocalRef(env Env, obj Object) {
+	C.DeleteLocalRef(env.value(), obj.value())
+}
+
 // GoRef creates a new reference to the value addressed by the provided pointer.
 // The value will remain referenced until it is explicitly unreferenced using
 // goUnref().