Merge branch 'master' into ble
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/impl/google/rpc/jni.go b/impl/google/rpc/jni.go
index dab6c3b..71b7816 100644
--- a/impl/google/rpc/jni.go
+++ b/impl/google/rpc/jni.go
@@ -18,7 +18,6 @@
 	"v.io/v23/vdl"
 	"v.io/v23/vom"
 
-	jchannel "v.io/x/jni/impl/google/channel"
 	jbt "v.io/x/jni/impl/google/rpc/protocols/bt"
 	jutil "v.io/x/jni/util"
 	jcontext "v.io/x/jni/v23/context"
@@ -66,8 +65,6 @@
 	jMountStatusClass jutil.Class
 	// Global reference for io.v.v23.rpc.NetworkAddress class.
 	jNetworkAddressClass jutil.Class
-	// Global reference for io.v.v23.rpc.NetworkChange class.
-	jNetworkChangeClass jutil.Class
 	// Global reference for io.v.v23.rpc.ProxyStatus class.
 	jProxyStatusClass jutil.Class
 	// Global reference for io.v.v23.rpc.ReflectInvoker class.
@@ -154,10 +151,6 @@
 	if err != nil {
 		return err
 	}
-	jNetworkChangeClass, err = jutil.JFindClass(env, "io/v/v23/rpc/NetworkChange")
-	if err != nil {
-		return err
-	}
 	jProxyStatusClass, err = jutil.JFindClass(env, "io/v/v23/rpc/ProxyStatus")
 	if err != nil {
 		return err
@@ -234,46 +227,6 @@
 	return C.jobject(unsafe.Pointer(jStatus))
 }
 
-//export Java_io_v_impl_google_rpc_ServerImpl_nativeWatchNetwork
-func Java_io_v_impl_google_rpc_ServerImpl_nativeWatchNetwork(jenv *C.JNIEnv, jServer C.jobject, goPtr C.jlong) C.jobject {
-	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
-	networkChan := make(chan rpc.NetworkChange, 100)
-	(*(*rpc.Server)(jutil.NativePtr(goPtr))).WatchNetwork(networkChan)
-	retChan := make(chan jutil.Object, 100)
-	go func() {
-		for change := range networkChan {
-			env, freeFunc := jutil.GetEnv()
-			jChange, err := JavaNetworkChange(env, change)
-			if err != nil {
-				freeFunc()
-				continue
-			}
-			jChange = jutil.NewGlobalRef(env, jChange)
-			freeFunc()
-			retChan <- jChange
-		}
-		close(retChan)
-	}()
-	jIterable, err := jchannel.JavaIterable(env, &retChan, &networkChan)
-	if err != nil {
-		jutil.JThrowV(env, err)
-		return nil
-	}
-	return C.jobject(unsafe.Pointer(jIterable))
-}
-
-//export Java_io_v_impl_google_rpc_ServerImpl_nativeUnwatchNetwork
-func Java_io_v_impl_google_rpc_ServerImpl_nativeUnwatchNetwork(jenv *C.JNIEnv, jServer C.jobject, goPtr C.jlong, jChannelIterable C.jobject) {
-	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
-	goNetworkChanPtr, err := jutil.CallLongMethod(env, jutil.Object(uintptr(unsafe.Pointer(jChannelIterable))), "getSourceNativePtr", nil)
-	if err != nil {
-		jutil.JThrowV(env, err)
-		return
-	}
-	networkChan := *(*chan rpc.NetworkChange)(unsafe.Pointer(uintptr(goNetworkChanPtr)))
-	(*(*rpc.Server)(jutil.NativePtr(goPtr))).UnwatchNetwork(networkChan)
-}
-
 //export Java_io_v_impl_google_rpc_ServerImpl_nativeStop
 func Java_io_v_impl_google_rpc_ServerImpl_nativeStop(jenv *C.JNIEnv, jServer C.jobject, goPtr C.jlong) {
 	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
diff --git a/impl/google/rpc/util.go b/impl/google/rpc/util.go
index a2f5df3..a7c7ead 100644
--- a/impl/google/rpc/util.go
+++ b/impl/google/rpc/util.go
@@ -265,36 +265,6 @@
 	return addrs, nil
 }
 
-// JavaNetworkChange converts the Go NetworkChange value into a Java NetworkChange object.
-func JavaNetworkChange(env jutil.Env, change rpc.NetworkChange) (jutil.Object, error) {
-	jTime, err := jutil.JTime(env, change.Time)
-	if err != nil {
-		return jutil.NullObject, err
-	}
-	jState, err := JavaServerState(env, change.State)
-	if err != nil {
-		return jutil.NullObject, err
-	}
-	jAddedAddrs, err := JavaNetworkAddressArray(env, change.AddedAddrs)
-	if err != nil {
-		return jutil.NullObject, err
-	}
-	jRemovedAddrs, err := JavaNetworkAddressArray(env, change.RemovedAddrs)
-	if err != nil {
-		return jutil.NullObject, err
-	}
-	changedEndpointStrs := make([]string, len(change.Changed))
-	for i, ep := range change.Changed {
-		changedEndpointStrs[i] = fmt.Sprintf("%v", ep)
-	}
-	addrSign := jutil.ClassSign("io.v.v23.rpc.NetworkAddress")
-	jNetworkChange, err := jutil.NewObject(env, jNetworkChangeClass, []jutil.Sign{jutil.DateTimeSign, serverStateSign, jutil.ArraySign(addrSign), jutil.ArraySign(addrSign), jutil.ArraySign(jutil.StringSign), jutil.VExceptionSign}, jTime, jState, jAddedAddrs, jRemovedAddrs, changedEndpointStrs, change.Error)
-	if err != nil {
-		return jutil.NullObject, err
-	}
-	return jNetworkChange, nil
-}
-
 // JavaServerCall converts a Go rpc.ServerCall into a Java ServerCall object.
 func JavaServerCall(env jutil.Env, serverCall rpc.ServerCall) (jutil.Object, error) {
 	jServerCall, err := jutil.NewObject(env, jServerCallImplClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&serverCall)))
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().