bind: split out Seq.getRef calls with Go references

Today, the Seq.Ref class has two purposes. For Java references,
Ref contains the refnum, a reference to the Java object and a
reference count. For Go references, Ref contains the refnum and
its finalizer makes sure to decrement the reference count on the Go
side.

The next CL will replace the use of finalizers with an explicit
ReferenceQueue of Go references, and the Ref class will no longer
be used for Go refences. To prepare for that, this CL pulls up the
construction of Go referencing Ref instances into the Seq.trackGoRef
function.

Change-Id: I9eefe238cd3fd1b661b2af11d331a2f61e31303b
Reviewed-on: https://go-review.googlesource.com/106875
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/bind/genjava.go b/bind/genjava.go
index 545f04f..ea66aec 100644
--- a/bind/genjava.go
+++ b/bind/genjava.go
@@ -303,11 +303,11 @@
 	}
 	if jinf == nil || jinf.genNoargCon {
 		// constructor for Go instantiated instances.
-		g.Printf("%s(Seq.Ref ref) { this.ref = ref; }\n\n", n)
+		g.Printf("%s(int refnum) { this.ref = Seq.trackGoRef(refnum); }\n\n", n)
 		if len(cons) == 0 {
 			// Generate default no-arg constructor
-			g.Printf("public %s() { this.ref = __New(); }\n\n", n)
-			g.Printf("private static native Seq.Ref __New();\n\n")
+			g.Printf("public %s() { this.ref = Seq.trackGoRef(__New()); }\n\n", n)
+			g.Printf("private static native int __New();\n\n")
 		}
 	}
 
@@ -420,7 +420,7 @@
 		}
 		g.Printf(");\n")
 	}
-	g.Printf("this.ref = ")
+	g.Printf("this.ref = Seq.trackGoRef(")
 	g.Printf("__%s(", f.Name())
 	for i := 0; i < params.Len(); i++ {
 		if i > 0 {
@@ -428,10 +428,10 @@
 		}
 		g.Printf(g.paramName(params, i))
 	}
-	g.Printf(");\n")
+	g.Printf("));\n")
 	g.Outdent()
 	g.Printf("}\n\n")
-	g.Printf("private static native Seq.Ref __%s(", f.Name())
+	g.Printf("private static native int __%s(", f.Name())
 	g.genFuncArgs(f, nil, false)
 	g.Printf(");\n\n")
 }
@@ -1118,7 +1118,7 @@
 	sig := f.Type().(*types.Signature)
 	res := sig.Results()
 
-	g.Printf("JNIEXPORT jobject JNICALL\n")
+	g.Printf("JNIEXPORT jint JNICALL\n")
 	g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__"+f.Name()))
 	params := sig.Params()
 	for i := 0; i < params.Len(); i++ {
@@ -1154,8 +1154,7 @@
 		g.genCToJava("_err", "res.r1", res.At(1).Type(), modeRetained)
 		g.Printf("go_seq_maybe_throw_exception(env, _err);\n")
 	}
-	// Pass no proxy class so that the Seq.Ref is returned instead.
-	g.Printf("return go_seq_from_refnum(env, refnum, NULL, NULL);\n")
+	g.Printf("return refnum;\n")
 	g.Outdent()
 	g.Printf("}\n\n")
 }
@@ -1481,13 +1480,13 @@
 		}
 		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(s.obj.Pkg())+g.javaTypeName(s.obj.Name()))
 		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, s.obj.Name())
-		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(Lgo/Seq$Ref;)V\");\n", g.pkgPrefix, s.obj.Name())
+		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, s.obj.Name())
 	}
 	for _, iface := range g.interfaces {
 		pkg := iface.obj.Pkg()
 		g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+JavaClassName(pkg)+"$proxy"+iface.obj.Name())
 		g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, iface.obj.Name())
-		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(Lgo/Seq$Ref;)V\");\n", g.pkgPrefix, iface.obj.Name())
+		g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(I)V\");\n", g.pkgPrefix, iface.obj.Name())
 		if isErrorType(iface.obj.Type()) {
 			// As a special case, Java Exceptions are passed to Go pretending to implement the Go error interface.
 			// To complete the illusion, use the Throwable.getMessage method for proxied calls to the error.Error method.
@@ -1532,12 +1531,10 @@
 			g.genJNIConstructor(f, sName)
 		}
 		if len(cons) == 0 && (jinf == nil || jinf.genNoargCon) {
-			g.Printf("JNIEXPORT jobject JNICALL\n")
+			g.Printf("JNIEXPORT jint JNICALL\n")
 			g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), java.JNIMangle(g.javaTypeName(sName)), java.JNIMangle("__New"))
 			g.Indent()
-			g.Printf("int32_t refnum = new_%s_%s();\n", g.pkgPrefix, sName)
-			// Pass no proxy class so that the Seq.Ref is returned instead.
-			g.Printf("return go_seq_from_refnum(env, refnum, NULL, NULL);\n")
+			g.Printf("return new_%s_%s();\n", g.pkgPrefix, sName)
 			g.Outdent()
 			g.Printf("}\n\n")
 		}
@@ -1604,7 +1601,7 @@
 		g.Printf(" implements Seq.Proxy, %s {\n", g.javaTypeName(n))
 		g.Indent()
 		g.genProxyImpl("proxy" + n)
-		g.Printf("proxy%s(Seq.Ref ref) { this.ref = ref; }\n\n", n)
+		g.Printf("proxy%s(int refnum) { this.ref = Seq.trackGoRef(refnum); }\n\n", n)
 
 		if isErrorType(iface.obj.Type()) {
 			g.Printf("@Override public String getMessage() { return error(); }\n\n")
diff --git a/bind/java/Seq.java b/bind/java/Seq.java
index b421a93..59a0880 100644
--- a/bind/java/Seq.java
+++ b/bind/java/Seq.java
@@ -66,6 +66,22 @@
 		return o.incRefnum();
 	}
 
+	// trackGoRef returns a Ref for a Go refnum.
+	//
+	// TODO(crawshaw): We could cut down allocations for frequently
+	// sent Go objects by maintaining a map to weak references. This
+	// however, would require allocating two objects per reference
+	// instead of one. It also introduces weak references, the bane
+	// of any Java debugging session.
+	//
+	// When we have real code, examine the tradeoffs.
+	public static Ref trackGoRef(int refnum) {
+		if (refnum > 0) {
+			throw new RuntimeException("trackGoRef called with Java refnum " + refnum);
+		}
+		return new Ref(refnum, null);
+	}
+
 	public static Ref getRef(int refnum) {
 		return tracker.get(refnum);
 	}
@@ -116,6 +132,9 @@
 		public final Object obj;  // for Java obj: pointers to the Java obj.
 
 		Ref(int refnum, Object o) {
+			if (refnum < 0) {
+				throw new RuntimeException("Ref instantiated with a Go refnum " + refnum);
+			}
 			this.refnum = refnum;
 			this.refcnt = 0;
 			this.obj = o;
@@ -221,29 +240,19 @@
 			}
 		}
 
-		// get returns an existing Ref to either a Java or Go object.
-		// It may be the first time we have seen the Go object.
-		//
-		// TODO(crawshaw): We could cut down allocations for frequently
-		// sent Go objects by maintaining a map to weak references. This
-		// however, would require allocating two objects per reference
-		// instead of one. It also introduces weak references, the bane
-		// of any Java debugging session.
-		//
-		// When we have real code, examine the tradeoffs.
+		// get returns an existing Ref to a Java object.
 		synchronized Ref get(int refnum) {
+			if (refnum < 0) {
+				throw new RuntimeException("ref called with Go refnum " + refnum);
+			}
 			if (refnum == NULL_REFNUM) {
 				return nullRef;
-			} else if (refnum > 0) {
-				Ref ref = javaObjs.get(refnum);
-				if (ref == null) {
-					throw new RuntimeException("unknown java Ref: "+refnum);
-				}
-				return ref;
-			} else {
-				// Go object.
-				return new Ref(refnum, null);
 			}
+			Ref ref = javaObjs.get(refnum);
+			if (ref == null) {
+				throw new RuntimeException("unknown java Ref: "+refnum);
+			}
+			return ref;
 		}
 	}
 
diff --git a/bind/java/seq_android.c.support b/bind/java/seq_android.c.support
index b3aafad..c4fafc2 100644
--- a/bind/java/seq_android.c.support
+++ b/bind/java/seq_android.c.support
@@ -250,23 +250,19 @@
 	if (refnum == NULL_REFNUM) {
 		return NULL;
 	}
+	if (refnum < 0) { // Go object
+		// return new <Proxy>(refnum)
+		return (*env)->NewObject(env, proxy_class, proxy_cons, refnum);
+	}
 	// Seq.Ref ref = Seq.getRef(refnum)
 	jobject ref = (*env)->CallStaticObjectMethod(env, seq_class, seq_getRef, (jint)refnum);
 	if (ref == NULL) {
 		LOG_FATAL("Unknown reference: %d", refnum);
 	}
-	if (refnum > 0) { // Java object
-		// Go incremented the reference count just before passing the refnum. Decrement it here.
-		(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)refnum);
-		// return ref.obj
-		return (*env)->GetObjectField(env, ref, ref_objField);
-	} else if (proxy_class != NULL) {
-		// return new <Proxy>(ref)
-		return (*env)->NewObject(env, proxy_class, proxy_cons, ref);
-	} else {
-		// We're inside a Java proxy constructor and only need the Seq.Ref
-		return ref;
-	}
+	// Go incremented the reference count just before passing the refnum. Decrement it here.
+	(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)refnum);
+	// return ref.obj
+	return (*env)->GetObjectField(env, ref, ref_objField);
 }
 
 // go_seq_to_java_string converts a nstring to a jstring.
diff --git a/bind/testdata/classes.java.c.golden b/bind/testdata/classes.java.c.golden
index bb0c974..dac9d2e 100644
--- a/bind/testdata/classes.java.c.golden
+++ b/bind/testdata/classes.java.c.golden
@@ -752,13 +752,13 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "java/Future");
     proxy_class_java_Future = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_Future_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_Future_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/Object");
     proxy_class_java_Object = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_Object_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_Object_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/Runnable");
     proxy_class_java_Runnable = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_Runnable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_Runnable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
 }
 
 JNIEXPORT jobject JNICALL
@@ -768,10 +768,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_java_Future__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_java_Future();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_java_Future();
 }
 
 JNIEXPORT jobject JNICALL
@@ -811,10 +810,10 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_java_InputStream__1_1NewInputStream(JNIEnv *env, jclass clazz) {
     int32_t refnum = proxyjava__NewInputStream();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return refnum;
 }
 
 JNIEXPORT jint JNICALL
@@ -842,10 +841,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_java_Object__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_java_Object();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_java_Object();
 }
 
 JNIEXPORT void JNICALL
@@ -863,10 +861,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_java_Runnable__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_java_Runnable();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_java_Runnable();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/classes.java.golden b/bind/testdata/classes.java.golden
index 9cc75b1..113927f 100644
--- a/bind/testdata/classes.java.golden
+++ b/bind/testdata/classes.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    Future(Seq.Ref ref) { this.ref = ref; }
+    Future(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public Future() { this.ref = __New(); }
+    public Future() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native java.util.concurrent.Future getFuture();
     public final native void setFuture(java.util.concurrent.Future v);
@@ -54,10 +54,10 @@
     
     public InputStream() {
         super();
-        this.ref = __NewInputStream();
+        this.ref = Seq.trackGoRef(__NewInputStream());
     }
     
-    private static native Seq.Ref __NewInputStream();
+    private static native int __NewInputStream();
     
     public final native java.io.InputStream getInputStream();
     public final native void setInputStream(java.io.InputStream v);
@@ -84,11 +84,11 @@
           return refnum;
     }
     
-    Object(Seq.Ref ref) { this.ref = ref; }
+    Object(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public Object() { this.ref = __New(); }
+    public Object() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native java.lang.Object getObject();
     public final native void setObject(java.lang.Object v);
@@ -114,11 +114,11 @@
           return refnum;
     }
     
-    Runnable(Seq.Ref ref) { this.ref = ref; }
+    Runnable(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public Runnable() { this.ref = __New(); }
+    public Runnable() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native java.lang.Runnable getRunnable();
     public final native void setRunnable(java.lang.Runnable v);
diff --git a/bind/testdata/doc.java.c.golden b/bind/testdata/doc.java.c.golden
index 3b300dc..5b07165 100644
--- a/bind/testdata/doc.java.c.golden
+++ b/bind/testdata/doc.java.c.golden
@@ -24,16 +24,16 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "doc/NoDoc");
     proxy_class_doc_NoDoc = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_doc_NoDoc_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_doc_NoDoc_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "doc/S");
     proxy_class_doc_S = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_doc_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_doc_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "doc/S2");
     proxy_class_doc_S2 = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_doc_S2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_doc_S2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "doc/Doc$proxyI");
     proxy_class_doc_I = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_doc_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_doc_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "doc/I");
     mid_I_IM = (*env)->GetMethodID(env, clazz, "im", "()V");
     
@@ -51,16 +51,15 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_doc_NoDoc__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_doc_NoDoc();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_doc_NoDoc();
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_doc_S__1_1NewS(JNIEnv *env, jclass clazz) {
     int32_t refnum = proxydoc__NewS();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return refnum;
 }
 
 JNIEXPORT void JNICALL
@@ -135,10 +134,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_doc_S2__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_doc_S2();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_doc_S2();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/doc.java.golden b/bind/testdata/doc.java.golden
index db94df5..6c62816 100644
--- a/bind/testdata/doc.java.golden
+++ b/bind/testdata/doc.java.golden
@@ -20,11 +20,11 @@
           return refnum;
     }
     
-    NoDoc(Seq.Ref ref) { this.ref = ref; }
+    NoDoc(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public NoDoc() { this.ref = __New(); }
+    public NoDoc() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     @Override public boolean equals(Object o) {
         if (o == null || !(o instanceof NoDoc)) {
@@ -71,12 +71,12 @@
      * NewS is a constructor.
      */
     public S() {
-        this.ref = __NewS();
+        this.ref = Seq.trackGoRef(__NewS());
     }
     
-    private static native Seq.Ref __NewS();
+    private static native int __NewS();
     
-    S(Seq.Ref ref) { this.ref = ref; }
+    S(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
     /**
      * SF is a field.
@@ -200,11 +200,11 @@
           return refnum;
     }
     
-    S2(Seq.Ref ref) { this.ref = ref; }
+    S2(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public S2() { this.ref = __New(); }
+    public S2() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     @Override public boolean equals(Object o) {
         if (o == null || !(o instanceof S2)) {
@@ -274,7 +274,7 @@
               return refnum;
         }
         
-        proxyI(Seq.Ref ref) { this.ref = ref; }
+        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void im();
     }
diff --git a/bind/testdata/ignore.java.c.golden b/bind/testdata/ignore.java.c.golden
index 6a29ff0..9511e21 100644
--- a/bind/testdata/ignore.java.c.golden
+++ b/bind/testdata/ignore.java.c.golden
@@ -23,10 +23,10 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "ignore/S");
     proxy_class_ignore_S = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_ignore_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_ignore_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "ignore/Ignore$proxyI");
     proxy_class_ignore_I = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_ignore_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_ignore_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "ignore/I");
     // skipped method I.Argument with unsupported parameter or return types
     
@@ -39,10 +39,9 @@
 
 // skipped function Result with unsupported parameter or return types
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_ignore_S__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_ignore_S();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_ignore_S();
 }
 
 // skipped function S.Argument with unsupported parameter or return types
diff --git a/bind/testdata/ignore.java.golden b/bind/testdata/ignore.java.golden
index d00b3b7..76aad8a 100644
--- a/bind/testdata/ignore.java.golden
+++ b/bind/testdata/ignore.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    S(Seq.Ref ref) { this.ref = ref; }
+    S(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public S() { this.ref = __New(); }
+    public S() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     // skipped field S.F with unsupported type: interface{}
     
@@ -96,7 +96,7 @@
               return refnum;
         }
         
-        proxyI(Seq.Ref ref) { this.ref = ref; }
+        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         // skipped method I.Argument with unsupported parameter or return types
         
diff --git a/bind/testdata/interfaces.java.c.golden b/bind/testdata/interfaces.java.c.golden
index 0f11d5d..b3c2138 100644
--- a/bind/testdata/interfaces.java.c.golden
+++ b/bind/testdata/interfaces.java.c.golden
@@ -43,56 +43,56 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyError");
     proxy_class_interfaces_Error = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_Error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_Error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/Error");
     mid_Error_Err = (*env)->GetMethodID(env, clazz, "err", "()V");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI");
     proxy_class_interfaces_I = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/I");
     mid_I_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI1");
     proxy_class_interfaces_I1 = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_I1_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_I1_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/I1");
     mid_I1_J = (*env)->GetMethodID(env, clazz, "j", "()V");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI2");
     proxy_class_interfaces_I2 = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_I2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_I2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/I2");
     mid_I2_G = (*env)->GetMethodID(env, clazz, "g", "()V");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI3");
     proxy_class_interfaces_I3 = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_I3_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_I3_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/I3");
     mid_I3_F = (*env)->GetMethodID(env, clazz, "f", "()Linterfaces/I1;");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyInterfaces");
     proxy_class_interfaces_Interfaces = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_Interfaces_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_Interfaces_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/Interfaces_");
     mid_Interfaces_SomeMethod = (*env)->GetMethodID(env, clazz, "someMethod", "()V");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyLargerI");
     proxy_class_interfaces_LargerI = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_LargerI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_LargerI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/LargerI");
     mid_LargerI_AnotherFunc = (*env)->GetMethodID(env, clazz, "anotherFunc", "()V");
     mid_LargerI_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxySameI");
     proxy_class_interfaces_SameI = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_SameI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_SameI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/SameI");
     mid_SameI_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
     
     clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyWithParam");
     proxy_class_interfaces_WithParam = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_interfaces_WithParam_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_interfaces_WithParam_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "interfaces/WithParam");
     mid_WithParam_HasParam = (*env)->GetMethodID(env, clazz, "hasParam", "(Z)V");
     
diff --git a/bind/testdata/interfaces.java.golden b/bind/testdata/interfaces.java.golden
index 87402b7..b7bfd86 100644
--- a/bind/testdata/interfaces.java.golden
+++ b/bind/testdata/interfaces.java.golden
@@ -159,7 +159,7 @@
               return refnum;
         }
         
-        proxyError(Seq.Ref ref) { this.ref = ref; }
+        proxyError(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void err() throws Exception;
     }
@@ -172,7 +172,7 @@
               return refnum;
         }
         
-        proxyI(Seq.Ref ref) { this.ref = ref; }
+        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native int rand();
     }
@@ -185,7 +185,7 @@
               return refnum;
         }
         
-        proxyI1(Seq.Ref ref) { this.ref = ref; }
+        proxyI1(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void j();
     }
@@ -198,7 +198,7 @@
               return refnum;
         }
         
-        proxyI2(Seq.Ref ref) { this.ref = ref; }
+        proxyI2(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void g();
     }
@@ -211,7 +211,7 @@
               return refnum;
         }
         
-        proxyI3(Seq.Ref ref) { this.ref = ref; }
+        proxyI3(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native I1 f();
     }
@@ -224,7 +224,7 @@
               return refnum;
         }
         
-        proxyInterfaces(Seq.Ref ref) { this.ref = ref; }
+        proxyInterfaces(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void someMethod();
     }
@@ -237,7 +237,7 @@
               return refnum;
         }
         
-        proxyLargerI(Seq.Ref ref) { this.ref = ref; }
+        proxyLargerI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void anotherFunc();
         public native int rand();
@@ -251,7 +251,7 @@
               return refnum;
         }
         
-        proxySameI(Seq.Ref ref) { this.ref = ref; }
+        proxySameI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native int rand();
     }
@@ -264,7 +264,7 @@
               return refnum;
         }
         
-        proxyWithParam(Seq.Ref ref) { this.ref = ref; }
+        proxyWithParam(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void hasParam(boolean p0);
     }
diff --git a/bind/testdata/issue10788.java.c.golden b/bind/testdata/issue10788.java.c.golden
index 7176a4d..c28be81 100644
--- a/bind/testdata/issue10788.java.c.golden
+++ b/bind/testdata/issue10788.java.c.golden
@@ -21,20 +21,19 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "issue10788/TestStruct");
     proxy_class_issue10788_TestStruct = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_issue10788_TestStruct_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_issue10788_TestStruct_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "issue10788/Issue10788$proxyTestInterface");
     proxy_class_issue10788_TestInterface = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_issue10788_TestInterface_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_issue10788_TestInterface_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "issue10788/TestInterface");
     mid_TestInterface_DoSomeWork = (*env)->GetMethodID(env, clazz, "doSomeWork", "(Lissue10788/TestStruct;)V");
     mid_TestInterface_MultipleUnnamedParams = (*env)->GetMethodID(env, clazz, "multipleUnnamedParams", "(JLjava/lang/String;J)V");
     
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_issue10788_TestStruct__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_issue10788_TestStruct();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_issue10788_TestStruct();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/issue10788.java.golden b/bind/testdata/issue10788.java.golden
index 75ea43d..7b7f4c4 100644
--- a/bind/testdata/issue10788.java.golden
+++ b/bind/testdata/issue10788.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    TestStruct(Seq.Ref ref) { this.ref = ref; }
+    TestStruct(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public TestStruct() { this.ref = __New(); }
+    public TestStruct() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native String getValue();
     public final native void setValue(String v);
@@ -99,7 +99,7 @@
               return refnum;
         }
         
-        proxyTestInterface(Seq.Ref ref) { this.ref = ref; }
+        proxyTestInterface(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void doSomeWork(TestStruct s);
         public native void multipleUnnamedParams(long p0, String p1, long p2);
diff --git a/bind/testdata/issue12328.java.c.golden b/bind/testdata/issue12328.java.c.golden
index de835cf..7c27e74 100644
--- a/bind/testdata/issue12328.java.c.golden
+++ b/bind/testdata/issue12328.java.c.golden
@@ -17,13 +17,12 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "issue12328/T");
     proxy_class_issue12328_T = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_issue12328_T_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_issue12328_T_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_issue12328_T__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_issue12328_T();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_issue12328_T();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/issue12328.java.golden b/bind/testdata/issue12328.java.golden
index db4d3da..1e69c1f 100644
--- a/bind/testdata/issue12328.java.golden
+++ b/bind/testdata/issue12328.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    T(Seq.Ref ref) { this.ref = ref; }
+    T(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public T() { this.ref = __New(); }
+    public T() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native java.lang.Exception getErr();
     public final native void setErr(java.lang.Exception v);
diff --git a/bind/testdata/issue12403.java.c.golden b/bind/testdata/issue12403.java.c.golden
index d9c9ce2..846473c 100644
--- a/bind/testdata/issue12403.java.c.golden
+++ b/bind/testdata/issue12403.java.c.golden
@@ -19,7 +19,7 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "issue12403/Issue12403$proxyParsable");
     proxy_class_issue12403_Parsable = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_issue12403_Parsable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_issue12403_Parsable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "issue12403/Parsable");
     mid_Parsable_FromJSON = (*env)->GetMethodID(env, clazz, "fromJSON", "(Ljava/lang/String;)Ljava/lang/String;");
     mid_Parsable_ToJSON = (*env)->GetMethodID(env, clazz, "toJSON", "()Ljava/lang/String;");
diff --git a/bind/testdata/issue12403.java.golden b/bind/testdata/issue12403.java.golden
index 290ef26..ec3548b 100644
--- a/bind/testdata/issue12403.java.golden
+++ b/bind/testdata/issue12403.java.golden
@@ -42,7 +42,7 @@
               return refnum;
         }
         
-        proxyParsable(Seq.Ref ref) { this.ref = ref; }
+        proxyParsable(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native String fromJSON(String jstr);
         public native String toJSON() throws Exception;
diff --git a/bind/testdata/java.java.c.golden b/bind/testdata/java.java.c.golden
index 607b5a9..99b5e7c 100644
--- a/bind/testdata/java.java.c.golden
+++ b/bind/testdata/java.java.c.golden
@@ -162,30 +162,30 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "java/Java$proxyF");
     proxy_class_java_F = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_F_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_F_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/F");
     mid_F_ToString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;");
     
     clazz = (*env)->FindClass(env, "java/Java$proxyL");
     proxy_class_java_L = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_L_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_L_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/L");
     mid_L_ToString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;");
     
     clazz = (*env)->FindClass(env, "java/Java$proxyO");
     proxy_class_java_O = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_O_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_O_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/O");
     mid_O_ToString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;");
     
     clazz = (*env)->FindClass(env, "java/Java$proxyR");
     proxy_class_java_R = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_R_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_R_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/R");
     
     clazz = (*env)->FindClass(env, "java/Java$proxyS");
     proxy_class_java_S = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_java_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_java_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/S");
     mid_S_ToString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;");
     
diff --git a/bind/testdata/java.java.golden b/bind/testdata/java.java.golden
index 22a2ec5..0042c9c 100644
--- a/bind/testdata/java.java.golden
+++ b/bind/testdata/java.java.golden
@@ -92,7 +92,7 @@
               return refnum;
         }
         
-        proxyF(Seq.Ref ref) { this.ref = ref; }
+        proxyF(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native String toString();
     }
@@ -105,7 +105,7 @@
               return refnum;
         }
         
-        proxyL(Seq.Ref ref) { this.ref = ref; }
+        proxyL(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native String toString();
     }
@@ -118,7 +118,7 @@
               return refnum;
         }
         
-        proxyO(Seq.Ref ref) { this.ref = ref; }
+        proxyO(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native String toString();
     }
@@ -131,7 +131,7 @@
               return refnum;
         }
         
-        proxyR(Seq.Ref ref) { this.ref = ref; }
+        proxyR(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
     }
     private static final class proxyS implements Seq.Proxy, S {
@@ -143,7 +143,7 @@
               return refnum;
         }
         
-        proxyS(Seq.Ref ref) { this.ref = ref; }
+        proxyS(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native String toString();
     }
diff --git a/bind/testdata/keywords.java.c.golden b/bind/testdata/keywords.java.c.golden
index 933410b..88571de 100644
--- a/bind/testdata/keywords.java.c.golden
+++ b/bind/testdata/keywords.java.c.golden
@@ -72,7 +72,7 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "keywords/Keywords$proxyKeywordCaller");
     proxy_class_keywords_KeywordCaller = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_keywords_KeywordCaller_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_keywords_KeywordCaller_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "keywords/KeywordCaller");
     mid_KeywordCaller_Abstract = (*env)->GetMethodID(env, clazz, "abstract_", "()V");
     mid_KeywordCaller_Assert = (*env)->GetMethodID(env, clazz, "assert_", "()V");
diff --git a/bind/testdata/keywords.java.golden b/bind/testdata/keywords.java.golden
index 9839bfe..11e056a 100644
--- a/bind/testdata/keywords.java.golden
+++ b/bind/testdata/keywords.java.golden
@@ -95,7 +95,7 @@
               return refnum;
         }
         
-        proxyKeywordCaller(Seq.Ref ref) { this.ref = ref; }
+        proxyKeywordCaller(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void abstract_();
         public native void assert_();
diff --git a/bind/testdata/structs.java.c.golden b/bind/testdata/structs.java.c.golden
index 0934a11..5a88adf 100644
--- a/bind/testdata/structs.java.c.golden
+++ b/bind/testdata/structs.java.c.golden
@@ -24,16 +24,16 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "structs/S");
     proxy_class_structs_S = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_structs_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_structs_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "structs/S2");
     proxy_class_structs_S2 = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_structs_S2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_structs_S2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "structs/Structs_");
     proxy_class_structs_Structs = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_structs_Structs_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_structs_Structs_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "structs/Structs$proxyI");
     proxy_class_structs_I = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_structs_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_structs_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "structs/I");
     mid_I_M = (*env)->GetMethodID(env, clazz, "m", "()V");
     
@@ -57,10 +57,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_structs_S__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_structs_S();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_structs_S();
 }
 
 JNIEXPORT jobject JNICALL
@@ -111,10 +110,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_structs_S2__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_structs_S2();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_structs_S2();
 }
 
 JNIEXPORT void JNICALL
@@ -131,10 +129,9 @@
     return _r0;
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_structs_Structs_1__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_structs_Structs();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_structs_Structs();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/structs.java.golden b/bind/testdata/structs.java.golden
index e1aed3f..e8d01ca 100644
--- a/bind/testdata/structs.java.golden
+++ b/bind/testdata/structs.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    S(Seq.Ref ref) { this.ref = ref; }
+    S(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public S() { this.ref = __New(); }
+    public S() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native double getX();
     public final native void setX(double v);
@@ -81,11 +81,11 @@
           return refnum;
     }
     
-    S2(Seq.Ref ref) { this.ref = ref; }
+    S2(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public S2() { this.ref = __New(); }
+    public S2() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public native void m();
     public native String string();
@@ -125,11 +125,11 @@
           return refnum;
     }
     
-    Structs_(Seq.Ref ref) { this.ref = ref; }
+    Structs_(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public Structs_() { this.ref = __New(); }
+    public Structs_() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public native void m();
     @Override public boolean equals(Object o) {
@@ -194,7 +194,7 @@
               return refnum;
         }
         
-        proxyI(Seq.Ref ref) { this.ref = ref; }
+        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         public native void m();
     }
diff --git a/bind/testdata/underscores.java.c.golden b/bind/testdata/underscores.java.c.golden
index a9d18f7..c617f01 100644
--- a/bind/testdata/underscores.java.c.golden
+++ b/bind/testdata/underscores.java.c.golden
@@ -17,7 +17,7 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "underscore_pkg/Underscore_struct");
     proxy_class_underscore_pkg_Underscore_struct = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_underscore_pkg_Underscore_struct_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_underscore_pkg_Underscore_struct_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
 }
 
 JNIEXPORT void JNICALL
@@ -25,10 +25,9 @@
     proxyunderscore_pkg__Underscore_func();
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_underscore_1pkg_Underscore_1struct__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_underscore_pkg_Underscore_struct();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_underscore_pkg_Underscore_struct();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/underscores.java.golden b/bind/testdata/underscores.java.golden
index fa1f8da..eae8f31 100644
--- a/bind/testdata/underscores.java.golden
+++ b/bind/testdata/underscores.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    Underscore_struct(Seq.Ref ref) { this.ref = ref; }
+    Underscore_struct(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public Underscore_struct() { this.ref = __New(); }
+    public Underscore_struct() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     public final native String getUnderscore_field();
     public final native void setUnderscore_field(String v);
diff --git a/bind/testdata/universe.java.c.golden b/bind/testdata/universe.java.c.golden
index 29ce3cd..71a481a 100644
--- a/bind/testdata/universe.java.c.golden
+++ b/bind/testdata/universe.java.c.golden
@@ -18,7 +18,7 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "go/Universe$proxyerror");
     proxy_class__error = (*env)->NewGlobalRef(env, clazz);
-    proxy_class__error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class__error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "java/lang/Throwable");
     mid_error_Error = (*env)->GetMethodID(env, clazz, "getMessage", "()Ljava/lang/String;");
 }
diff --git a/bind/testdata/universe.java.golden b/bind/testdata/universe.java.golden
index f01d6b2..1b60067 100644
--- a/bind/testdata/universe.java.golden
+++ b/bind/testdata/universe.java.golden
@@ -41,7 +41,7 @@
               return refnum;
         }
         
-        proxyerror(Seq.Ref ref) { this.ref = ref; }
+        proxyerror(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
         @Override public String getMessage() { return error(); }
         
diff --git a/bind/testdata/vars.java.c.golden b/bind/testdata/vars.java.c.golden
index ff5e77c..aacc9cd 100644
--- a/bind/testdata/vars.java.c.golden
+++ b/bind/testdata/vars.java.c.golden
@@ -19,18 +19,17 @@
     jclass clazz;
     clazz = (*env)->FindClass(env, "vars/S");
     proxy_class_vars_S = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_vars_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_vars_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "vars/Vars$proxyI");
     proxy_class_vars_I = (*env)->NewGlobalRef(env, clazz);
-    proxy_class_vars_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
+    proxy_class_vars_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
     clazz = (*env)->FindClass(env, "vars/I");
     
 }
 
-JNIEXPORT jobject JNICALL
+JNIEXPORT jint JNICALL
 Java_vars_S__1_1New(JNIEnv *env, jclass clazz) {
-    int32_t refnum = new_vars_S();
-    return go_seq_from_refnum(env, refnum, NULL, NULL);
+    return new_vars_S();
 }
 
 JNIEXPORT void JNICALL
diff --git a/bind/testdata/vars.java.golden b/bind/testdata/vars.java.golden
index 2e6b49d..4161af7 100644
--- a/bind/testdata/vars.java.golden
+++ b/bind/testdata/vars.java.golden
@@ -17,11 +17,11 @@
           return refnum;
     }
     
-    S(Seq.Ref ref) { this.ref = ref; }
+    S(int refnum) { this.ref = Seq.trackGoRef(refnum); }
     
-    public S() { this.ref = __New(); }
+    public S() { this.ref = Seq.trackGoRef(__New()); }
     
-    private static native Seq.Ref __New();
+    private static native int __New();
     
     @Override public boolean equals(Object o) {
         if (o == null || !(o instanceof S)) {
@@ -84,7 +84,7 @@
               return refnum;
         }
         
-        proxyI(Seq.Ref ref) { this.ref = ref; }
+        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
         
     }