Merge "veyron/runtimes/google/ipc/jni: split JNI files across dirs and cleaned up interfaces."
diff --git a/runtimes/google/ipc/jni/arg_getter.go b/runtimes/google/ipc/jni/arg_getter.go
index 4cb0c6e..7479f00 100644
--- a/runtimes/google/ipc/jni/arg_getter.go
+++ b/runtimes/google/ipc/jni/arg_getter.go
@@ -1,4 +1,4 @@
-package main
+package jni
 
 import (
 	"fmt"
@@ -8,7 +8,7 @@
 	// Imported VDLs.  Please add a link to all VDLs you care about here,
 	// and add all interfaces you care about to the init() function below.
 	"veyron/examples/fortune"
-	"veyron2/context"
+	ctx "veyron2/context"
 	"veyron2/ipc"
 )
 
@@ -32,7 +32,7 @@
 		panic(fmt.Sprintf("expected interface type for %q, got: %v", ifacePtr, t.Kind()))
 	}
 
-	contextType := reflect.TypeOf((*context.T)(nil)).Elem()
+	contextType := reflect.TypeOf((*ctx.T)(nil)).Elem()
 	serverContextType := reflect.TypeOf((*ipc.ServerContext)(nil)).Elem()
 	optType := reflect.TypeOf(([]ipc.CallOpt)(nil))
 	// Create a new arg getter.
diff --git a/runtimes/google/ipc/jni/arg_getter_test.go b/runtimes/google/ipc/jni/arg_getter_test.go
index f931770..f5429e4 100644
--- a/runtimes/google/ipc/jni/arg_getter_test.go
+++ b/runtimes/google/ipc/jni/arg_getter_test.go
@@ -1,4 +1,4 @@
-package main
+package jni
 
 import (
 	"reflect"
diff --git a/runtimes/google/ipc/jni/client.go b/runtimes/google/ipc/jni/client.go
index 571f8ae..e3fb714 100644
--- a/runtimes/google/ipc/jni/client.go
+++ b/runtimes/google/ipc/jni/client.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"encoding/json"
@@ -12,6 +12,7 @@
 	"veyron2/ipc"
 )
 
+// #cgo LDFLAGS: -ljniwrapper
 // #include <stdlib.h>
 // #include "jni_wrapper.h"
 import "C"
@@ -38,11 +39,11 @@
 	// Get argument instances that correspond to the provided method.
 	getter := newArgGetter(strings.Join(strings.Split(goString(env, jPath), ".")[1:], "/"))
 	if getter == nil {
-		return nil, fmt.Errorf("couldn't find IDL interface corresponding to path %q", goString(env, jPath))
+		return nil, fmt.Errorf("couldn't find VDL interface corresponding to path %q", goString(env, jPath))
 	}
 	mArgs := getter.FindMethod(method, len(argStrs))
 	if mArgs == nil {
-		return nil, fmt.Errorf("couldn't find method %s with %d args in IDL interface at path %q, getter: %v", method, len(argStrs), goString(env, jPath), getter)
+		return nil, fmt.Errorf("couldn't find method %s with %d args in VDL interface at path %q, getter: %v", method, len(argStrs), goString(env, jPath), getter)
 	}
 	argptrs := mArgs.InPtrs()
 	if len(argptrs) != len(argStrs) {
diff --git a/runtimes/google/ipc/jni/context.go b/runtimes/google/ipc/jni/context.go
index cecb04e..dec30c7 100644
--- a/runtimes/google/ipc/jni/context.go
+++ b/runtimes/google/ipc/jni/context.go
@@ -1,12 +1,13 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"fmt"
 	"runtime"
 )
 
+// #cgo LDFLAGS: -ljniwrapper
 // #include "jni_wrapper.h"
 import "C"
 
diff --git a/runtimes/google/ipc/jni/dispatcher.go b/runtimes/google/ipc/jni/dispatcher.go
index 1d8b56d..f8fa818 100644
--- a/runtimes/google/ipc/jni/dispatcher.go
+++ b/runtimes/google/ipc/jni/dispatcher.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"fmt"
@@ -10,6 +10,7 @@
 	"veyron2/security"
 )
 
+// #cgo LDFLAGS: -ljniwrapper
 // #include "jni_wrapper.h"
 // // CGO doesn't support variadic functions so we have to hard-code these
 // // functions to match the invoking code. Ugh!
diff --git a/runtimes/google/ipc/jni/dummy.go b/runtimes/google/ipc/jni/dummy.go
deleted file mode 100644
index 8532d1b..0000000
--- a/runtimes/google/ipc/jni/dummy.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// +build !android
-
-package main
-
-func main() {}
diff --git a/runtimes/google/ipc/jni/invoker.go b/runtimes/google/ipc/jni/invoker.go
index 74a1c90..5c62670 100644
--- a/runtimes/google/ipc/jni/invoker.go
+++ b/runtimes/google/ipc/jni/invoker.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"encoding/json"
@@ -13,7 +13,7 @@
 	"veyron2/verror"
 )
 
-// #cgo LDFLAGS: -llog
+// #cgo LDFLAGS: -llog -ljniwrapper
 // #include <stdlib.h>
 // #include <android/log.h>
 // #include "jni_wrapper.h"
@@ -35,18 +35,18 @@
 import "C"
 
 func newJNIInvoker(env *C.JNIEnv, jVM *C.JavaVM, jObj C.jobject) (ipc.Invoker, error) {
-	// Create a new Java IDLInvoker object.
-	cid := jMethodID(env, jIDLInvokerClass, "<init>", fmt.Sprintf("(%s)%s", objectSign, voidSign))
-	jInvoker := C.CallNewInvokerObject(env, jIDLInvokerClass, cid, jObj)
+	// Create a new Java VDLInvoker object.
+	cid := jMethodID(env, jVDLInvokerClass, "<init>", fmt.Sprintf("(%s)%s", objectSign, voidSign))
+	jInvoker := C.CallNewInvokerObject(env, jVDLInvokerClass, cid, jObj)
 	if err := jExceptionMsg(env); err != nil {
-		return nil, fmt.Errorf("error creating Java IDLInvoker object: %v", err)
+		return nil, fmt.Errorf("error creating Java VDLInvoker object: %v", err)
 	}
 	// Fetch the argGetter for the object.
-	pid := jMethodID(env, jIDLInvokerClass, "getInterfacePath", fmt.Sprintf("()%s", stringSign))
+	pid := jMethodID(env, jVDLInvokerClass, "getInterfacePath", fmt.Sprintf("()%s", stringSign))
 	jPath := C.jstring(C.CallGetInterfacePath(env, jInvoker, pid))
 	getter := newArgGetter(strings.Join(strings.Split(goString(env, jPath), ".")[1:], "/"))
 	if getter == nil {
-		return nil, fmt.Errorf("couldn't find IDL interface corresponding to path %q", goString(env, jPath))
+		return nil, fmt.Errorf("couldn't find VDL interface corresponding to path %q", goString(env, jPath))
 	}
 	// Reference Java invoker; it will be de-referenced when the go invoker
 	// created below is garbage-collected (through the finalizer callback we
@@ -80,7 +80,7 @@
 	// pending VOM encoder/decoder changes as well as Java (de)serializer.
 	mArgs := i.argGetter.FindMethod(method, numArgs)
 	if mArgs == nil {
-		err = fmt.Errorf("couldn't find IDL method %q with %d args", method, numArgs)
+		err = fmt.Errorf("couldn't find VDL method %q with %d args", method, numArgs)
 		return
 	}
 	argptrs = mArgs.InPtrs()
@@ -104,7 +104,7 @@
 	// Create a new Java server call instance.
 	mArgs := i.argGetter.FindMethod(method, len(argptrs))
 	if mArgs == nil {
-		err = fmt.Errorf("couldn't find IDL method %q with %d args", method, len(argptrs))
+		err = fmt.Errorf("couldn't find VDL method %q with %d args", method, len(argptrs))
 	}
 	sCall := newServerCall(call, mArgs)
 	cid := jMethodID(env, jServerCallClass, "<init>", fmt.Sprintf("(%s)%s", longSign, voidSign))
@@ -118,7 +118,7 @@
 	}
 	// Invoke the method.
 	const callSign = "Lcom/veyron2/ipc/ServerCall;"
-	const replySign = "Lcom/veyron/runtimes/google/ipc/IDLInvoker$InvokeReply;"
+	const replySign = "Lcom/veyron/runtimes/google/VDLInvoker$InvokeReply;"
 	mid := jMethodID(env, C.GetObjectClass(env, i.jInvoker), "invoke", fmt.Sprintf("(%s%s[%s)%s", stringSign, callSign, stringSign, replySign))
 	jReply := C.CallInvokeMethod(env, i.jInvoker, mid, jString(env, camelCase(method)), jServerCall, jArgs)
 	if err := jExceptionMsg(env); err != nil {
diff --git a/runtimes/google/ipc/jni/jni.go b/runtimes/google/ipc/jni/jni.go
index c010140..d9e6a98 100644
--- a/runtimes/google/ipc/jni/jni.go
+++ b/runtimes/google/ipc/jni/jni.go
@@ -1,21 +1,20 @@
 // +build android
 
-package main
+package jni
 
 import (
-	"flag"
 	"fmt"
 	"io"
 	"time"
-	"unsafe"
 
 	"veyron2"
+	ctx "veyron2/context"
 	"veyron2/ipc"
 	"veyron2/rt"
 )
 
 // #include <stdlib.h>
-// #include "jni_wrapper.h"
+// #include <jni.h>
 import "C"
 
 var (
@@ -23,8 +22,8 @@
 	jVeyronExceptionClass C.jclass
 	// Global reference for com.veyron.runtimes.google.ipc.Runtime$ServerCall class.
 	jServerCallClass C.jclass
-	// Global reference for com.veyron.runtimes.google.ipc.IDLInvoker class.
-	jIDLInvokerClass C.jclass
+	// Global reference for com.veyron.runtimes.google.ipc.VDLInvoker class.
+	jVDLInvokerClass C.jclass
 	// Global reference for java.lang.Throwable class.
 	jThrowableClass C.jclass
 	// Global reference for java.lang.String class.
@@ -33,26 +32,21 @@
 	jEOFExceptionClass C.jclass
 )
 
-//export JNI_OnLoad
-func JNI_OnLoad(jVM *C.JavaVM, reserved unsafe.Pointer) C.jint {
-	return C.JNI_VERSION_1_6
-}
-
-//export Java_com_veyron_runtimes_google_ipc_Runtime_nativeGlobalInit
-func Java_com_veyron_runtimes_google_ipc_Runtime_nativeGlobalInit(env *C.JNIEnv, jRuntime C.jclass) {
+//export Java_com_veyron_runtimes_google_Runtime_nativeGlobalInit
+func Java_com_veyron_runtimes_google_Runtime_nativeGlobalInit(env *C.JNIEnv, jRuntime C.jclass) {
 	// Cache global references to all Java classes used by the package.  This is
 	// necessary because JNI gets access to the class loader only in the system
 	// thread, so we aren't able to invoke FindClass in other threads.
 	jVeyronExceptionClass = jFindClassOrDie(env, "com/veyron2/ipc/VeyronException")
-	jServerCallClass = jFindClassOrDie(env, "com/veyron/runtimes/google/ipc/Runtime$ServerCall")
-	jIDLInvokerClass = jFindClassOrDie(env, "com/veyron/runtimes/google/ipc/IDLInvoker")
+	jServerCallClass = jFindClassOrDie(env, "com/veyron/runtimes/google/Runtime$ServerCall")
+	jVDLInvokerClass = jFindClassOrDie(env, "com/veyron/runtimes/google/VDLInvoker")
 	jThrowableClass = jFindClassOrDie(env, "java/lang/Throwable")
 	jStringClass = jFindClassOrDie(env, "java/lang/String")
 	jEOFExceptionClass = jFindClassOrDie(env, "java/io/EOFException")
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeInit
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeInit(env *C.JNIEnv, jRuntime C.jobject, create C.jboolean) C.jlong {
+//export Java_com_veyron_runtimes_google_Runtime_nativeInit
+func Java_com_veyron_runtimes_google_Runtime_nativeInit(env *C.JNIEnv, jRuntime C.jobject, create C.jboolean) C.jlong {
 	r := rt.Init()
 	if create == C.JNI_TRUE {
 		var err error
@@ -65,14 +59,18 @@
 	return ptrValue(&r)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewClient
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewClient(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
-	r, ok := ptr(goRuntimePtr).(*veyron2.Runtime)
-	if !ok || r == nil {
+//export Java_com_veyron_runtimes_google_Runtime_nativeNewClient
+func Java_com_veyron_runtimes_google_Runtime_nativeNewClient(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong, timeoutMillis C.jlong) C.jlong {
+	r := (*veyron2.Runtime)(ptr(goRuntimePtr))
+	if r == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go runtime with pointer: %d", int(goRuntimePtr)))
 		return C.jlong(0)
 	}
-	rc, err := (*r).NewClient()
+	options := []ipc.ClientOpt{}
+	if int(timeoutMillis) > 0 {
+		options = append(options, veyron2.CallTimeout(time.Duration(timeoutMillis)*time.Millisecond))
+	}
+	rc, err := (*r).NewClient(options...)
 	if err != nil {
 		jThrowV(env, err)
 		return C.jlong(0)
@@ -82,10 +80,10 @@
 	return ptrValue(c)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewServer
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewServer(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
-	r, ok := ptr(goRuntimePtr).(*veyron2.Runtime)
-	if !ok || r == nil {
+//export Java_com_veyron_runtimes_google_Runtime_nativeNewServer
+func Java_com_veyron_runtimes_google_Runtime_nativeNewServer(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
+	r := (*veyron2.Runtime)(ptr(goRuntimePtr))
+	if r == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go runtime with pointer: %d", int(goRuntimePtr)))
 		return C.jlong(0)
 	}
@@ -98,10 +96,10 @@
 	return ptrValue(&s)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeGetClient
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeGetClient(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
-	r, ok := ptr(goRuntimePtr).(*veyron2.Runtime)
-	if !ok || r == nil {
+//export Java_com_veyron_runtimes_google_Runtime_nativeGetClient
+func Java_com_veyron_runtimes_google_Runtime_nativeGetClient(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
+	r := (*veyron2.Runtime)(ptr(goRuntimePtr))
+	if r == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go runtime with pointer: %d", int(goRuntimePtr)))
 		return C.jlong(0)
 	}
@@ -111,10 +109,10 @@
 	return ptrValue(c)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewContext
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeNewContext(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
-	r, ok := ptr(goRuntimePtr).(*veyron2.Runtime)
-	if !ok || r == nil {
+//export Java_com_veyron_runtimes_google_Runtime_nativeNewContext
+func Java_com_veyron_runtimes_google_Runtime_nativeNewContext(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) C.jlong {
+	r := (*veyron2.Runtime)(ptr(goRuntimePtr))
+	if r == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go runtime with pointer: %d", int(goRuntimePtr)))
 		return C.jlong(0)
 	}
@@ -123,18 +121,18 @@
 	return ptrValue(&c)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Runtime_nativeFinalize(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) {
-	r, ok := ptr(goRuntimePtr).(*veyron2.Runtime)
-	if ok && r != nil {
+//export Java_com_veyron_runtimes_google_Runtime_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_nativeFinalize(env *C.JNIEnv, jRuntime C.jobject, goRuntimePtr C.jlong) {
+	r := (*veyron2.Runtime)(ptr(goRuntimePtr))
+	if r != nil {
 		goUnref(r)
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativeRegister
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativeRegister(env *C.JNIEnv, jServer C.jobject, goServerPtr C.jlong, prefix C.jstring, dispatcher C.jobject) {
-	s, ok := ptr(goServerPtr).(*ipc.Server)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Server_nativeRegister
+func Java_com_veyron_runtimes_google_Runtime_00024Server_nativeRegister(env *C.JNIEnv, jServer C.jobject, goServerPtr C.jlong, prefix C.jstring, dispatcher C.jobject) {
+	s := (*ipc.Server)(ptr(goServerPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server with pointer: %d", int(goServerPtr)))
 		return
 	}
@@ -147,10 +145,10 @@
 	(*s).Register(goString(env, prefix), d)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativeListen
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativeListen(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong, protocol C.jstring, address C.jstring) C.jstring {
-	s, ok := ptr(goServerPtr).(*ipc.Server)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Server_nativeListen
+func Java_com_veyron_runtimes_google_Runtime_00024Server_nativeListen(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong, protocol C.jstring, address C.jstring) C.jstring {
+	s := (*ipc.Server)(ptr(goServerPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server with pointer: %d", int(goServerPtr)))
 		return nil
 	}
@@ -162,10 +160,10 @@
 	return jString(env, ep.String())
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativePublish
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Server_nativePublish(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong, name C.jstring) {
-	s, ok := ptr(goServerPtr).(*ipc.Server)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Server_nativePublish
+func Java_com_veyron_runtimes_google_Runtime_00024Server_nativePublish(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong, name C.jstring) {
+	s := (*ipc.Server)(ptr(goServerPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server with pointer: %d", int(goServerPtr)))
 		return
 	}
@@ -175,10 +173,10 @@
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_jni_Runtime_00024Server_nativeStop
-func Java_com_veyron_runtimes_google_ipc_jni_Runtime_00024Server_nativeStop(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
-	s, ok := ptr(goServerPtr).(*ipc.Server)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeStop
+func Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeStop(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
+	s := (*ipc.Server)(ptr(goServerPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server with pointer: %d", int(goServerPtr)))
 		return
 	}
@@ -188,18 +186,18 @@
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_jni_Runtime_00024Server_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_jni_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
-	s, ok := ptr(goServerPtr).(*ipc.Server)
-	if ok && s != nil {
+//export Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize
+func Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
+	s := (*ipc.Server)(ptr(goServerPtr))
+	if s != nil {
 		goUnref(s)
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeStartCall
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeStartCall(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong, jContext C.jobject, name C.jstring, method C.jstring, jsonArgs C.jobjectArray, jPath C.jstring, timeoutMillis C.jlong) C.jlong {
-	c, ok := ptr(goClientPtr).(*client)
-	if !ok || c == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Client_nativeStartCall
+func Java_com_veyron_runtimes_google_Runtime_00024Client_nativeStartCall(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong, jContext C.jobject, name C.jstring, method C.jstring, jsonArgs C.jobjectArray, jPath C.jstring, timeoutMillis C.jlong) C.jlong {
+	c := (*client)(ptr(goClientPtr))
+	if c == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go client with pointer: %d", int(goClientPtr)))
 		return C.jlong(0)
 	}
@@ -212,46 +210,46 @@
 	return ptrValue(call)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeClose
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeClose(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong) {
-	c, ok := ptr(goClientPtr).(*client)
-	if !ok || c == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Client_nativeClose
+func Java_com_veyron_runtimes_google_Runtime_00024Client_nativeClose(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong) {
+	c := (*client)(ptr(goClientPtr))
+	if c == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go client with pointer: %d", int(goClientPtr)))
 		return
 	}
 	c.Close()
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Client_nativeFinalize(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong) {
-	c, ok := ptr(goClientPtr).(*client)
-	if ok && c != nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Client_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024Client_nativeFinalize(env *C.JNIEnv, jClient C.jobject, goClientPtr C.jlong) {
+	c := (*client)(ptr(goClientPtr))
+	if c != nil {
 		goUnref(c)
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Context_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Context_nativeFinalize(env *C.JNIEnv, jClient C.jobject, goContextPtr C.jlong) {
-	c, ok := ptr(goContextPtr).(*ipc.Context)
-	if ok && c != nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Context_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024Context_nativeFinalize(env *C.JNIEnv, jClient C.jobject, goContextPtr C.jlong) {
+	c := (*ctx.T)(ptr(goContextPtr))
+	if c != nil {
 		goUnref(c)
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Stream_nativeSend
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Stream_nativeSend(env *C.JNIEnv, jStream C.jobject, goStreamPtr C.jlong, jItem C.jstring) {
-	s, ok := ptr(goStreamPtr).(*stream)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Stream_nativeSend
+func Java_com_veyron_runtimes_google_Runtime_00024Stream_nativeSend(env *C.JNIEnv, jStream C.jobject, goStreamPtr C.jlong, jItem C.jstring) {
+	s := (*stream)(ptr(goStreamPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go stream with pointer: %d", int(goStreamPtr)))
 		return
 	}
 	s.Send(env, jItem)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024Stream_nativeRecv
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024Stream_nativeRecv(env *C.JNIEnv, jStream C.jobject, goStreamPtr C.jlong) C.jstring {
-	s, ok := ptr(goStreamPtr).(*stream)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024Stream_nativeRecv
+func Java_com_veyron_runtimes_google_Runtime_00024Stream_nativeRecv(env *C.JNIEnv, jStream C.jobject, goStreamPtr C.jlong) C.jstring {
+	s := (*stream)(ptr(goStreamPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go stream with pointer: %d", int(goStreamPtr)))
 		return nil
 	}
@@ -267,10 +265,10 @@
 	return ret
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeFinish
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeFinish(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) C.jobjectArray {
-	c, ok := ptr(goClientCallPtr).(*clientCall)
-	if !ok || c == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeFinish
+func Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeFinish(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) C.jobjectArray {
+	c := (*clientCall)(ptr(goClientCallPtr))
+	if c == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go client call with pointer: %d", int(goClientCallPtr)))
 		return nil
 	}
@@ -282,28 +280,28 @@
 	return ret
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeCancel
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeCancel(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) {
-	c, ok := ptr(goClientCallPtr).(*clientCall)
-	if !ok || c == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeCancel
+func Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeCancel(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) {
+	c := (*clientCall)(ptr(goClientCallPtr))
+	if c == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go client call with pointer: %d", int(goClientCallPtr)))
 		return
 	}
 	c.Cancel()
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ClientCall_nativeFinalize(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) {
-	c, ok := ptr(goClientCallPtr).(*clientCall)
-	if ok && c != nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024ClientCall_nativeFinalize(env *C.JNIEnv, jClientCall C.jobject, goClientCallPtr C.jlong) {
+	c := (*clientCall)(ptr(goClientCallPtr))
+	if c != nil {
 		goUnref(c)
 	}
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeDeadline
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeDeadline(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) C.jlong {
-	s, ok := ptr(goServerCallPtr).(*serverCall)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeDeadline
+func Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeDeadline(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) C.jlong {
+	s := (*serverCall)(ptr(goServerCallPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server call with pointer: %d", int(goServerCallPtr)))
 		return C.jlong(0)
 	}
@@ -317,10 +315,10 @@
 	return C.jlong(d.UnixNano() / 1000)
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeClosed
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeClosed(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) C.jboolean {
-	s, ok := ptr(goServerCallPtr).(*serverCall)
-	if !ok || s == nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeClosed
+func Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeClosed(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) C.jboolean {
+	s := (*serverCall)(ptr(goServerCallPtr))
+	if s == nil {
 		jThrowV(env, fmt.Errorf("Couldn't find Go server call with pointer: %d", int(goServerCallPtr)))
 		return C.JNI_FALSE
 	}
@@ -330,17 +328,10 @@
 	return C.JNI_FALSE
 }
 
-//export Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeFinalize
-func Java_com_veyron_runtimes_google_ipc_Runtime_00024ServerCall_nativeFinalize(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) {
-	s, ok := ptr(goServerCallPtr).(*serverCall)
-	if ok && s != nil {
+//export Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024ServerCall_nativeFinalize(env *C.JNIEnv, jServerCall C.jobject, goServerCallPtr C.jlong) {
+	s := (*serverCall)(ptr(goServerCallPtr))
+	if s != nil {
 		goUnref(s)
 	}
 }
-
-func main() {
-	// Send all logging to stderr, so that the output is visible in Android.  Note that if this
-	// flag is removed, the process will likely crash as android requires that all logs are written
-	// into a specific directory.
-	flag.Set("logtostderr", "true")
-}
diff --git a/runtimes/google/ipc/jni/jni_wrapper.c b/runtimes/google/ipc/jni/jni_wrapper.c
deleted file mode 100644
index 88d9991..0000000
--- a/runtimes/google/ipc/jni/jni_wrapper.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// +build android
-
-#include "jni_wrapper.h"
-
-jclass GetObjectClass(JNIEnv* env, jobject obj) {
-  return (*env)->GetObjectClass(env, obj);
-}
-
-jclass FindClass(JNIEnv* env, const char* name) {
-  return (*env)->FindClass(env, name);
-}
-
-jmethodID GetMethodID(JNIEnv* env, jclass class, const char* name, const char* args) {
-  return (*env)->GetMethodID(env, class, name, args);
-}
-
-jfieldID GetFieldID(JNIEnv* env, jclass class, const char* name, const char* sig) {
-  return (*env)->GetFieldID(env, class, name, sig);
-}
-
-jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID) {
-  return (*env)->GetBooleanField(env, obj, fieldID);
-}
-
-jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID) {
-  return (*env)->GetObjectField(env, obj, fieldID);
-}
-
-jobjectArray NewObjectArray(JNIEnv* env, jsize len, jclass class, jobject obj) {
-  return (*env)->NewObjectArray(env, len, class, obj);
-}
-
-jsize GetArrayLength(JNIEnv* env, jarray array) {
-  return (*env)->GetArrayLength(env, array);
-}
-
-jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
-  return (*env)->GetObjectArrayElement(env, array, index);
-}
-
-void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject obj) {
-  (*env)->SetObjectArrayElement(env, array, index, obj);
-}
-
-const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy) {
-  return (*env)->GetStringUTFChars(env, str, isCopy);
-}
-
-void ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* utf) {
-  (*env)->ReleaseStringUTFChars(env, str, utf);
-}
-
-jstring NewStringUTF(JNIEnv* env, const char* str) {
-  return (*env)->NewStringUTF(env, str);
-}
-
-jint Throw(JNIEnv* env, jthrowable obj) {
-  return (*env)->Throw(env, obj);
-}
-
-jint ThrowNew(JNIEnv* env, jclass class, const char* msg) {
-  return (*env)->ThrowNew(env, class, msg);
-}
-
-jobject NewGlobalRef(JNIEnv* env, jobject obj) {
-  return (*env)->NewGlobalRef(env, obj);
-}
-
-void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
-  return (*env)->DeleteGlobalRef(env, globalRef);
-}
-
-jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
-  return (*env)->GetJavaVM(env, vm);
-}
-
-jthrowable ExceptionOccurred(JNIEnv* env) {
-  return (*env)->ExceptionOccurred(env);
-}
-
-void ExceptionClear(JNIEnv* env) {
-  return (*env)->ExceptionClear(env);
-}
-
-jint AttachCurrentThread(JavaVM* jvm, JNIEnv** env, void* args) {
-  return (*jvm)->AttachCurrentThread(jvm, env, args);
-}
-
-jint DetachCurrentThread(JavaVM* jvm) {
-  return (*jvm)->DetachCurrentThread(jvm);
-}
\ No newline at end of file
diff --git a/runtimes/google/ipc/jni/jni_wrapper.h b/runtimes/google/ipc/jni/jni_wrapper.h
deleted file mode 100644
index ef50307..0000000
--- a/runtimes/google/ipc/jni/jni_wrapper.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// +build android
-
-#ifndef VEYRON_RUNTIMES_GOOGLE_IPC_JNI_JNI_WRAPPERS_H
-#define VEYRON_RUNTIMES_GOOGLE_IPC_JNI_JNI_WRAPPERS_H
-
-#include <jni.h>
-
-// Go cannot invoke function pointers (which is what JNI requires for all
-// construct of type (*env)->GetMethodID(...)), so we have to create C stubs
-// below to do the job.
-
-// Returns the class of an object.
-jclass GetObjectClass(JNIEnv* env, jobject obj);
-
-// Searches the directories and zip files specified by the CLASSPATH environment
-// variable for the class with the specified name.
-jclass FindClass(JNIEnv* env, const char* name);
-
-// Returns the method ID for an instance (nonstatic) method of a class or
-// interface.
-jmethodID GetMethodID(JNIEnv* env, jclass class, const char* name, const char* args);
-
-// Returns the field ID for an instance (nonstatic) field of a class.
-jfieldID GetFieldID(JNIEnv* env, jclass class, const char* name, const char* sig);
-
-// Returns the value of an instance (nonstatic) boolean field of the provided
-// object.
-jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID);
-
-// Returns the value of an instance (nonstatic) Object field of the provided
-// object.
-jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID);
-
-// Constructs a new array holding objects in class jclass.
-jobjectArray NewObjectArray(JNIEnv* env, jsize len, jclass class, jobject obj);
-
-// Returns the number of elements in the array.
-jsize GetArrayLength(JNIEnv* env, jarray array);
-
-// Returns an element of an Object array.
-jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index);
-
-// Sets an element of an Object array.
-void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject obj);
-
-// Returns a pointer to an array of bytes representing the string in modified
-// UTF-8 encoding.
-const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy);
-
-// Informs the VM that the native code no longer needs access to the byte array.
-void ReleaseStringUTFChars(JNIEnv* env, jstring str, const char* utf);
-
-// Constructs a new java.lang.String object from an array of characters in
-// modified UTF-8 encoding.
-jstring NewStringUTF(JNIEnv* env, const char* str);
-
-// Causes a java.lang.Throwable object to be thrown.
-jint Throw(JNIEnv* env, jthrowable obj);
-
-// Constructs an exception object from the specified class with the given
-// message and causes that exception to be thrown.
-jint ThrowNew(JNIEnv* env, jclass class, const char* msg);
-
-// Creates a new global reference to the object referred to by the obj argument.
-jobject NewGlobalRef(JNIEnv* env, jobject obj);
-
-// Deletes the global reference pointed to by globalRef.
-void DeleteGlobalRef(JNIEnv* env, jobject globalRef);
-
-// Returns the Java VM interface (used in the Invocation API) associated with
-// the current thread.
-jint GetJavaVM(JNIEnv* env, JavaVM** vm);
-
-// Determines if an exception is being thrown.
-jthrowable ExceptionOccurred(JNIEnv* env);
-
-// Clears any exception that is currently being thrown.
-void ExceptionClear(JNIEnv* env);
-
-// Attaches the current thread to a Java VM.
-jint AttachCurrentThread(JavaVM* jvm, JNIEnv** env, void* args);
-
-// Detaches the current thread from a Java VM.
-jint DetachCurrentThread(JavaVM* jvm);
-
-#endif /* VEYRON_RUNTIMES_GOOGLE_IPC_JNI_JNI_WRAPPERS_H */
\ No newline at end of file
diff --git a/runtimes/google/ipc/jni/log_android.go b/runtimes/google/ipc/jni/log_android.go
index 2bd096f..1194169 100644
--- a/runtimes/google/ipc/jni/log_android.go
+++ b/runtimes/google/ipc/jni/log_android.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 // #cgo LDFLAGS: -llog
 // #include <android/log.h>
diff --git a/runtimes/google/ipc/jni/server_call.go b/runtimes/google/ipc/jni/server_call.go
index ffab2ff..a9d3f6d 100644
--- a/runtimes/google/ipc/jni/server_call.go
+++ b/runtimes/google/ipc/jni/server_call.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"veyron2/ipc"
diff --git a/runtimes/google/ipc/jni/stream.go b/runtimes/google/ipc/jni/stream.go
index dc4a2fa..0ef6751 100644
--- a/runtimes/google/ipc/jni/stream.go
+++ b/runtimes/google/ipc/jni/stream.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"encoding/json"
@@ -10,7 +10,7 @@
 )
 
 // #include <stdlib.h>
-// #include "jni_wrapper.h"
+// #include <jni.h>
 import "C"
 
 func newStream(s ipc.Stream, mArgs *methodArgs) stream {
diff --git a/runtimes/google/ipc/jni/util.go b/runtimes/google/ipc/jni/util.go
index 50041ef..b122926 100644
--- a/runtimes/google/ipc/jni/util.go
+++ b/runtimes/google/ipc/jni/util.go
@@ -1,6 +1,6 @@
 // +build android
 
-package main
+package jni
 
 import (
 	"errors"
@@ -14,6 +14,7 @@
 	"veyron2/verror"
 )
 
+// #cgo LDFLAGS: -ljniwrapper
 // #include <stdlib.h>
 // #include "jni_wrapper.h"
 // // CGO doesn't support variadic functions so we have to hard-code these
@@ -69,14 +70,13 @@
 }
 
 // ptr returns the pointer represented by the provided (Java C.jlong) value.
-func ptr(ptrValue C.jlong) (ptr interface{}) {
-	ptr = unsafe.Pointer(uintptr(ptrValue))
-	return
+func ptr(ptrValue C.jlong) unsafe.Pointer {
+	return unsafe.Pointer(uintptr(ptrValue))
 }
 
 // isPointer returns true iff the provided value is a pointer.
 func isPointer(val interface{}) bool {
-	return reflect.ValueOf(ptr).Kind() == reflect.Ptr
+	return reflect.ValueOf(val).Kind() == reflect.Ptr
 }
 
 // goString returns a Go string given the Java string.