[mobile] mobile/bind: don't force Java classes to extend stub classes

32 views
Skip to first unread message

Elias Naur (Gerrit)

unread,
Mar 30, 2016, 1:11:46 PM3/30/16
to Ian Lance Taylor, golang-co...@googlegroups.com
Elias Naur uploaded a change:
https://go-review.googlesource.com/21313

mobile/bind: don't force Java classes to extend stub classes

Requiring user code to extend Go interface Stubs to be able to pass
Java objects to Go is clumsy and use up the single extend slot.
Instead, support (and encourage) java classes that implement
translated Go interface directly. This is similar to how ObjC works.

The stub classes are not special anymore, but keep them for backwards
compatibility for now. Also, mark them @Deprecated to signal their
uselessness.

Change-Id: I880bb7c8e89d3c21210b2ab2c85ced8d7859ff48
---
M bind/genjava.go
M bind/java/Seq.java
M bind/java/SeqBench.java
M bind/java/SeqTest.java
M bind/java/seq_android.c.support
M bind/testdata/ignore.java.golden
M bind/testdata/interfaces.java.golden
M bind/testdata/issue10788.java.golden
M bind/testdata/issue12328.java.golden
M bind/testdata/issue12403.java.golden
M bind/testdata/structs.java.golden
M bind/testdata/vars.java.golden
M cmd/gobind/doc.go
13 files changed, 173 insertions(+), 328 deletions(-)



diff --git a/bind/genjava.go b/bind/genjava.go
index cd66ac5..89468a2 100644
--- a/bind/genjava.go
+++ b/bind/genjava.go
@@ -27,7 +27,7 @@
fields := exportedFields(T)
methods := exportedMethodSet(types.NewPointer(obj.Type()))

- impls := []string{"go.Seq.Object"}
+ var impls []string
pT := types.NewPointer(obj.Type())
for _, iface := range g.allIntf {
if types.AssignableTo(pT, iface.obj.Type()) {
@@ -38,14 +38,15 @@
impls = append(impls, n)
}
}
- g.Printf("public static final class %s implements %s {\n", obj.Name(),
strings.Join(impls, ", "))
+ g.Printf("public static final class %s extends Seq.Proxy", obj.Name())
+ if len(impls) > 0 {
+ g.Printf(" implements %s", strings.Join(impls, ", "))
+ }
+ g.Printf(" {\n")
g.Indent()

- g.Printf("private final go.Seq.Ref ref;\n\n")
-
n := obj.Name()
- g.Printf("private %s(go.Seq.Ref ref) { this.ref = ref; }\n\n", n)
- g.Printf("public final go.Seq.Ref ref() { return ref; }\n\n")
+ g.Printf("private %s(go.Seq.Ref ref) { super(ref); }\n\n", n)

for _, f := range fields {
if t := f.Type(); !g.isSupported(t) {
@@ -137,19 +138,11 @@
}

func (g *javaGen) genInterfaceStub(o *types.TypeName, m *types.Interface) {
- g.Printf("public static abstract class Stub implements %s {\n", o.Name())
- g.Indent()
-
- g.Printf("private final go.Seq.Ref ref;\n")
- g.Printf("public Stub() {\n ref = go.Seq.createRef(this);\n}\n\n")
- g.Printf("public final go.Seq.Ref ref() { return ref; }\n\n")
-
- g.Outdent()
- g.Printf("}\n\n")
+ g.Printf("@Deprecated\npublic static abstract class Stub implements %s
{}\n\n", o.Name())
}

func (g *javaGen) genInterface(iface interfaceInfo) {
- exts := []string{"go.Seq.Object"}
+ var exts []string
numM := iface.t.NumMethods()
for _, other := range g.allIntf {
// Only extend interfaces with fewer methods to avoid circular references
@@ -161,7 +154,11 @@
exts = append(exts, n)
}
}
- g.Printf("public interface %s extends %s {\n", iface.obj.Name(),
strings.Join(exts, ", "))
+ g.Printf("public interface %s", iface.obj.Name())
+ if len(exts) > 0 {
+ g.Printf(" extends %s", strings.Join(exts, ", "))
+ }
+ g.Printf(" {\n")
g.Indent()

methodSigErr := false
@@ -1099,12 +1096,8 @@
}

const (
- javaProxyPreamble = `static final class Proxy implements %s {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ javaProxyPreamble = `static final class Proxy extends Seq.Proxy
implements %s {
+ Proxy(Seq.Ref ref) { super(ref); }

`
javaPreamble = `// Java class %[1]s.%[2]s is a proxy for talking to a Go
program.
diff --git a/bind/java/Seq.java b/bind/java/Seq.java
index ce36935..f2907c2 100644
--- a/bind/java/Seq.java
+++ b/bind/java/Seq.java
@@ -5,6 +5,7 @@
package go;

import java.util.Arrays;
+import java.util.HashMap;
import java.util.logging.Logger;

// Seq is a sequence of machine-dependent encoded values.
@@ -15,7 +16,7 @@
// also known to bind/seq/ref.go and bind/objc/seq_darwin.m
private static final int NULL_REFNUM = 41;

- // use single Ref for null Seq.Object
+ // use single Ref for null Object
public static final Ref nullRef = new Ref(NULL_REFNUM, null);

static {
@@ -51,14 +52,11 @@
static native void setContext(java.lang.Object ctx);

public static void incRefnum(int refnum) {
- Ref ref = tracker.get(refnum);
- tracker.inc(ref);
+ tracker.incRefnum(refnum);
}

- public static int incRef(Seq.Object o) {
- Ref ref = o.ref();
- tracker.inc(ref);
- return ref.refnum;
+ public static int incRef(Object o) {
+ return tracker.inc(o);
}

public static Ref getRef(int refnum) {
@@ -71,31 +69,33 @@
// Informs the Go ref tracker that Java is done with this ref.
static native void destroyRef(int refnum);

- // createRef creates a Ref to a Java object.
- public static Ref createRef(Seq.Object o) {
- return tracker.createRef(o);
- }
-
// decRef is called from seq.FinalizeRef
static void decRef(int refnum) {
tracker.dec(refnum);
}

- // An Object is a Java object that matches a Go object.
- // The implementation of the object may be in either Java or Go,
- // with a proxy instance in the other language passing calls
- // through to the other language.
- //
- // Don't implement an Object directly. Instead, look for the
- // generated abstract Stub.
- public interface Object {
- public Ref ref();
+ // A Proxy is a Java object that proxies a Go object.
+ public static abstract class Proxy {
+ private final Ref ref;
+
+ protected Proxy(Ref ref) {
+ this.ref = ref;
+ }
+
+ public final int incRefnum() {
+ // The Go reference count need to be bumped while the
+ // refnum is passed to Go, to avoid finalizing and
+ // invalidating it before being translated on the Go side.
+ int refnum = ref.refnum;
+ incGoRef(refnum);
+ return refnum;
+ }
}

// A Ref is an object tagged with an integer for passing back and
// forth across the language boundary.
//
- // A Ref may represent either an instance of a Java Object subclass,
+ // A Ref may represent either an instance of a Java object,
// or an instance of a Go object. The explicit allocation of a Ref
// is used to pin Go object instances when they are passed to Java.
// The Go Seq library maintains a reference to the instance in a map
@@ -106,11 +106,11 @@
// refnum > 0: Java object tracked by Go
public final int refnum;

- int refcnt; // for Java obj: track how many times sent to Go.
+ private int refcnt; // for Java obj: track how many times sent to Go.

- public final Seq.Object obj; // for Java obj: pointers to the Java obj.
+ public final Object obj; // for Java obj: pointers to the Java obj.

- Ref(int refnum, Seq.Object o) {
+ Ref(int refnum, Object o) {
this.refnum = refnum;
this.refcnt = 0;
this.obj = o;
@@ -123,6 +123,14 @@
Seq.destroyRef(refnum);
}
super.finalize();
+ }
+
+ void inc() {
+ // Count how many times this ref's Java object is passed to Go.
+ if (refcnt == Integer.MAX_VALUE) {
+ throw new RuntimeException("refnum " + refnum + " overflow");
+ }
+ refcnt++;
}
}

@@ -142,32 +150,44 @@
// The Ref obj field is non-null.
// This map pins Java objects so they don't get GCed while the
// only reference to them is held by Go code.
- private RefMap javaObjs = new RefMap();
+ private final RefMap javaObjs = new RefMap();
+
+ // Java objects to refnum
+ private final HashMap<Object, Integer> javaRefs = new HashMap<>();

// inc increments the reference count of a Java object when it
- // is sent to Go.
- synchronized void inc(Ref ref) {
- int refnum = ref.refnum;
- if (refnum <= 0) {
- // We don't keep track of the Go object ourselves, but
- // the Go reference count need to be bumped while the
- // refnum is passed to Go, to avoid finalizing and
- // invalidating it before being translated on the Go side.
- incGoRef(refnum);
- return;
+ // is sent to Go. inc returns the refnum for the object.
+ synchronized int inc(Object o) {
+ if (o == null) {
+ return NULL_REFNUM;
}
- if (refnum == NULL_REFNUM) {
- return;
+ if (o instanceof Proxy) {
+ return ((Proxy)o).incRefnum();
}
- // Count how many times this ref's Java object is passed to Go.
- if (ref.refcnt == Integer.MAX_VALUE) {
- throw new RuntimeException("refnum " + refnum + " overflow");
+ Integer refnumObj = javaRefs.get(o);
+ if (refnumObj == null) {
+ if (next == Integer.MAX_VALUE) {
+ throw new RuntimeException("createRef overflow for " + o);
+ }
+ refnumObj = next++;
+ javaRefs.put(o, refnumObj);
}
- ref.refcnt++;
- Ref obj = javaObjs.get(refnum);
- if (obj == null) {
+ int refnum = refnumObj;
+ Ref ref = javaObjs.get(refnum);
+ if (ref == null) {
+ ref = new Ref(refnum, o);
javaObjs.put(refnum, ref);
}
+ ref.inc();
+ return refnum;
+ }
+
+ synchronized void incRefnum(int refnum) {
+ Ref ref = javaObjs.get(refnum);
+ if (ref == null) {
+ throw new RuntimeException("referenced Java object is not found:
refnum="+refnum);
+ }
+ ref.inc();
}

// dec decrements the reference count of a Java object when
@@ -192,19 +212,8 @@
obj.refcnt--;
if (obj.refcnt <= 0) {
javaObjs.remove(refnum);
+ javaRefs.remove(obj.obj);
}
- }
-
- synchronized Ref createRef(Seq.Object o) {
- if (o == null) {
- return Seq.nullRef;
- }
- if (next == Integer.MAX_VALUE) {
- throw new RuntimeException("createRef overflow for " + o);
- }
- int refnum = next++;
- Ref ref = new Ref(refnum, o);
- return ref;
}

// get returns an existing Ref to either a Java or Go object.
diff --git a/bind/java/SeqBench.java b/bind/java/SeqBench.java
index 95dfc28..e28754f 100644
--- a/bind/java/SeqBench.java
+++ b/bind/java/SeqBench.java
@@ -17,12 +17,12 @@

public class SeqBench extends InstrumentationTestCase {

- public static class AnI extends Benchmark.I.Stub {
+ public static class AnI implements Benchmark.I {
@Override public void F() {
}
}

- private static class Benchmarks extends Benchmark.Benchmarks.Stub {
+ private static class Benchmarks implements Benchmark.Benchmarks {
private static Map<String, Runnable> benchmarks;
private static ExecutorService executor =
Executors.newSingleThreadExecutor();

diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java
index b5dc9a4..30763f7 100644
--- a/bind/java/SeqTest.java
+++ b/bind/java/SeqTest.java
@@ -216,7 +216,7 @@
assertEquals("S should be collected", 1, collected);
}

- private class AnI extends Testpkg.I.Stub {
+ private class AnI implements Testpkg.I {
public void E() throws Exception {
throw new Exception("my exception from E");
}
@@ -355,7 +355,7 @@

private int countI = 0;

- private class CountI extends Testpkg.I.Stub {
+ private class CountI implements Testpkg.I {
public void F() { countI++; }

public void E() throws Exception {}
@@ -425,7 +425,7 @@

//test if we have JNI local reference table overflow error
public void testLocalReferenceOverflow() {
- Testpkg.CallWithCallback(new Testpkg.GoCallback.Stub() {
+ Testpkg.CallWithCallback(new Testpkg.GoCallback() {

@Override
public void VarUpdate() {
@@ -435,7 +435,7 @@
}

public void testNullReferences() {
- assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest.Stub() {
+ assertTrue(Testpkg.CallWithNull(null, new Testpkg.NullTest() {
public Testpkg.NullTest Null() {
return null;
}
@@ -445,7 +445,7 @@
}

public void testPassByteArray() {
- Testpkg.PassByteArray(new Testpkg.B.Stub() {
+ Testpkg.PassByteArray(new Testpkg.B() {
@Override public void B(byte[] b) {
byte[] want = new byte[]{1, 2, 3, 4};
MoreAsserts.assertEquals("bytes should match", want, b);
@@ -468,14 +468,14 @@
}

public void testGoroutineCallback() {
- Testpkg.GoroutineCallback(new Testpkg.Receiver.Stub() {
+ Testpkg.GoroutineCallback(new Testpkg.Receiver() {
@Override public void Hello(String msg) {
}
});
}

public void testImportedPkg() {
- Testpkg.CallImportedI(new Secondpkg.I.Stub() {
+ Testpkg.CallImportedI(new Secondpkg.I() {
@Override public long F(long i) {
return i;
}
@@ -505,13 +505,13 @@
public void testRoundtripEquality() {
Testpkg.I want = new AnI();
assertTrue("java object passed through Go should not be wrapped", want
== Testpkg.IDup(want));
- Testpkg.InterfaceDupper idup = new Testpkg.InterfaceDupper.Stub(){
+ Testpkg.InterfaceDupper idup = new Testpkg.InterfaceDupper(){
@Override public Testpkg.Interface IDup(Testpkg.Interface i) {
return i;
}
};
assertTrue("Go interface passed through Java should not be wrapped",
Testpkg.CallIDupper(idup));
- Testpkg.ConcreteDupper cdup = new Testpkg.ConcreteDupper.Stub(){
+ Testpkg.ConcreteDupper cdup = new Testpkg.ConcreteDupper(){
@Override public Testpkg.Concrete CDup(Testpkg.Concrete c) {
return c;
}
diff --git a/bind/java/seq_android.c.support
b/bind/java/seq_android.c.support
index 5e9702e..d02d732 100644
--- a/bind/java/seq_android.c.support
+++ b/bind/java/seq_android.c.support
@@ -307,7 +307,7 @@
if (seq_incRefnum == NULL) {
LOG_FATAL("failed to find method Seq.incRefnum");
}
- seq_incRef = (*env)->GetStaticMethodID(env,
seq_class, "incRef", "(Lgo/Seq$Object;)I");
+ seq_incRef = (*env)->GetStaticMethodID(env,
seq_class, "incRef", "(Ljava/lang/Object;)I");
if (seq_incRef == NULL) {
LOG_FATAL("failed to find method Seq.incRef");
}
@@ -323,7 +323,7 @@
if (ref_class == NULL) {
LOG_FATAL("failed to find the Seq.Ref class");
}
- ref_objField = (*env)->GetFieldID(env,
ref_class, "obj", "Lgo/Seq$Object;");
+ ref_objField = (*env)->GetFieldID(env,
ref_class, "obj", "Ljava/lang/Object;");
if (ref_objField == NULL) {
LOG_FATAL("failed to find the Seq.Ref.obj field");
}
diff --git a/bind/testdata/ignore.java.golden
b/bind/testdata/ignore.java.golden
index 4ffbbb9..d7103be 100644
--- a/bind/testdata/ignore.java.golden
+++ b/bind/testdata/ignore.java.golden
@@ -19,12 +19,8 @@

private static native void init();

- public static final class S implements go.Seq.Object, I {
- private final go.Seq.Ref ref;
-
- private S(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class S extends Seq.Proxy implements I {
+ private S(go.Seq.Ref ref) { super(ref); }

// skipped field S.F with unsupported type: *types.Interface

@@ -53,27 +49,16 @@
}
}

- public interface I extends go.Seq.Object {
+ public interface I {
// skipped method I.Argument with unsupported parameter or return
types

// skipped method I.Result with unsupported parameter or return
types

- public static abstract class Stub implements I {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements I {}

- static final class Proxy implements I {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I {
+ Proxy(Seq.Ref ref) { super(ref); }

// skipped method I.Argument with unsupported parameter or
return types

diff --git a/bind/testdata/interfaces.java.golden
b/bind/testdata/interfaces.java.golden
index 9dd7c19..ff7e374 100644
--- a/bind/testdata/interfaces.java.golden
+++ b/bind/testdata/interfaces.java.golden
@@ -19,167 +19,93 @@

private static native void init();

- public interface Error extends go.Seq.Object {
+ public interface Error {
public void Err() throws Exception;
- public static abstract class Stub implements Error {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements Error {}

- static final class Proxy implements Error {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements Error {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void Err() throws Exception;
}
}

- public interface I extends go.Seq.Object {
+ public interface I {
public int Rand();
- public static abstract class Stub implements I {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements I {}

- static final class Proxy implements I {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I {
+ Proxy(Seq.Ref ref) { super(ref); }

public native int Rand();
}
}

- public interface I1 extends go.Seq.Object {
+ public interface I1 {
public void J();
- static final class Proxy implements I1 {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I1 {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void J();
}
}

- public interface I2 extends go.Seq.Object {
+ public interface I2 {
public void G();
- static final class Proxy implements I2 {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I2 {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void G();
}
}

- public interface I3 extends go.Seq.Object {
+ public interface I3 {
public I1 F();
- public static abstract class Stub implements I3 {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements I3 {}

- static final class Proxy implements I3 {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I3 {
+ Proxy(Seq.Ref ref) { super(ref); }

public native I1 F();
}
}

- public interface LargerI extends go.Seq.Object, I, SameI {
+ public interface LargerI extends I, SameI {
public void AnotherFunc();
public int Rand();
- public static abstract class Stub implements LargerI {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements LargerI {}

- static final class Proxy implements LargerI {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements LargerI {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void AnotherFunc();
public native int Rand();
}
}

- public interface SameI extends go.Seq.Object {
+ public interface SameI {
public int Rand();
- public static abstract class Stub implements SameI {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements SameI {}

- static final class Proxy implements SameI {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements SameI {
+ Proxy(Seq.Ref ref) { super(ref); }

public native int Rand();
}
}

- public interface WithParam extends go.Seq.Object {
+ public interface WithParam {
public void HasParam(boolean p0);
- public static abstract class Stub implements WithParam {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements WithParam {}

- static final class Proxy implements WithParam {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements WithParam {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void HasParam(boolean p0);
}
diff --git a/bind/testdata/issue10788.java.golden
b/bind/testdata/issue10788.java.golden
index cf73bd5..aa0cc98 100644
--- a/bind/testdata/issue10788.java.golden
+++ b/bind/testdata/issue10788.java.golden
@@ -19,12 +19,8 @@

private static native void init();

- public static final class TestStruct implements go.Seq.Object {
- private final go.Seq.Ref ref;
-
- private TestStruct(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class TestStruct extends Seq.Proxy {
+ private TestStruct(go.Seq.Ref ref) { super(ref); }

public final native String getValue();
public final native void setValue(String v);
@@ -58,25 +54,14 @@
}
}

- public interface TestInterface extends go.Seq.Object {
+ public interface TestInterface {
public void DoSomeWork(TestStruct s);
public void MultipleUnnamedParams(long p0, String p1, long p2);
- public static abstract class Stub implements TestInterface {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements TestInterface {}

- static final class Proxy implements TestInterface {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements
TestInterface {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void DoSomeWork(TestStruct s);
public native void MultipleUnnamedParams(long p0, String p1,
long p2);
diff --git a/bind/testdata/issue12328.java.golden
b/bind/testdata/issue12328.java.golden
index 7af1892..1a01f48 100644
--- a/bind/testdata/issue12328.java.golden
+++ b/bind/testdata/issue12328.java.golden
@@ -19,12 +19,8 @@

private static native void init();

- public static final class T implements go.Seq.Object {
- private final go.Seq.Ref ref;
-
- private T(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class T extends Seq.Proxy {
+ private T(go.Seq.Ref ref) { super(ref); }

public final native String getErr();
public final native void setErr(String v);
diff --git a/bind/testdata/issue12403.java.golden
b/bind/testdata/issue12403.java.golden
index 90c074b..3506708 100644
--- a/bind/testdata/issue12403.java.golden
+++ b/bind/testdata/issue12403.java.golden
@@ -19,25 +19,14 @@

private static native void init();

- public interface Parsable extends go.Seq.Object {
+ public interface Parsable {
public String FromJSON(String jstr);
public String ToJSON() throws Exception;
- public static abstract class Stub implements Parsable {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements Parsable {}

- static final class Proxy implements Parsable {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements Parsable {
+ Proxy(Seq.Ref ref) { super(ref); }

public native String FromJSON(String jstr);
public native String ToJSON() throws Exception;
diff --git a/bind/testdata/structs.java.golden
b/bind/testdata/structs.java.golden
index 3333e9f..92cff64 100644
--- a/bind/testdata/structs.java.golden
+++ b/bind/testdata/structs.java.golden
@@ -19,12 +19,8 @@

private static native void init();

- public static final class S implements go.Seq.Object {
- private final go.Seq.Ref ref;
-
- private S(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class S extends Seq.Proxy {
+ private S(go.Seq.Ref ref) { super(ref); }

public final native double getX();
public final native void setX(double v);
@@ -65,12 +61,8 @@
}
}

- public static final class S2 implements go.Seq.Object, I {
- private final go.Seq.Ref ref;
-
- private S2(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class S2 extends Seq.Proxy implements I {
+ private S2(go.Seq.Ref ref) { super(ref); }

public native void M();
public native String String();
@@ -91,24 +83,13 @@
}
}

- public interface I extends go.Seq.Object {
+ public interface I {
public void M();
- public static abstract class Stub implements I {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ @Deprecated
+ public static abstract class Stub implements I {}

- static final class Proxy implements I {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I {
+ Proxy(Seq.Ref ref) { super(ref); }

public native void M();
}
diff --git a/bind/testdata/vars.java.golden b/bind/testdata/vars.java.golden
index f232b6e..3e2284d 100644
--- a/bind/testdata/vars.java.golden
+++ b/bind/testdata/vars.java.golden
@@ -19,12 +19,8 @@

private static native void init();

- public static final class S implements go.Seq.Object, I {
- private final go.Seq.Ref ref;
-
- private S(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ public static final class S extends Seq.Proxy implements I {
+ private S(go.Seq.Ref ref) { super(ref); }

@Override public boolean equals(Object o) {
if (o == null || !(o instanceof S)) {
@@ -45,23 +41,12 @@
}
}

- public interface I extends go.Seq.Object {
- public static abstract class Stub implements I {
- private final go.Seq.Ref ref;
- public Stub() {
- ref = go.Seq.createRef(this);
- }
-
- public final go.Seq.Ref ref() { return ref; }
-
- }
+ public interface I {
+ @Deprecated
+ public static abstract class Stub implements I {}

- static final class Proxy implements I {
- private go.Seq.Ref ref;
-
- Proxy(go.Seq.Ref ref) { this.ref = ref; }
-
- public final go.Seq.Ref ref() { return ref; }
+ static final class Proxy extends Seq.Proxy implements I {
+ Proxy(Seq.Ref ref) { super(ref); }

}
}
diff --git a/cmd/gobind/doc.go b/cmd/gobind/doc.go
index 8faf054..af81798 100644
--- a/cmd/gobind/doc.go
+++ b/cmd/gobind/doc.go
@@ -90,16 +90,12 @@
p.Print("Hello, World!")
}

-gobind generates a Java stub that can be used to implement a Printer:
+gobind generates a Java interface that can be used to implement a Printer:

public abstract class Myfmt {
private Myfmt() {}
public interface Printer {
public void Print(String s);
-
- public static abstract class Stub implements Printer {
- ...
- }

...
}
@@ -107,10 +103,10 @@
public static void PrintHello(Printer p) { ... }
}

-You can extend Myfmt.Printer.Stub to implement the Printer interface, and
-pass it to Go using the PrintHello package function:
+You can implement Myfmt.Printer, and pass it to Go using the PrintHello
+package function:

- public class SysPrint extends Myfmt.Printer.Stub {
+ public class SysPrint implements Myfmt.Printer {
public void Print(String s) {
System.out.println(s);
}
@@ -205,8 +201,8 @@
even if they are otherwise unreachable.

We recommend that implementations of foreign interfaces do not hold
-references to proxies of objects. That is: if you extend a Stub in
-Java, do not store an instance of Seq.Object inside it.
+references to proxies of objects. That is: if you implement a Go
+interface in Java, do not store an instance of Seq.Object inside it.

Further reading


--
https://go-review.googlesource.com/21313

Elias Naur (Gerrit)

unread,
Mar 30, 2016, 1:22:14 PM3/30/16
to golang-co...@googlegroups.com
Elias Naur uploaded a new patch set:
--
https://go-review.googlesource.com/21313

Elias Naur (Gerrit)

unread,
Mar 30, 2016, 2:25:32 PM3/30/16
to golang-co...@googlegroups.com
Elias Naur uploaded a new patch set:
--
https://go-review.googlesource.com/21313

David Crawshaw (Gerrit)

unread,
Mar 30, 2016, 4:14:32 PM3/30/16
to Elias Naur, golang-co...@googlegroups.com
David Crawshaw has posted comments on this change.

mobile/bind: don't force Java classes to extend stub classes

Patch Set 3: Code-Review+2

Very nice.

I don't think backwards compatibility is too important, no promise of
stability has been made yet. If you want to remove the deprecated generated
classes, go ahead.

Could the generated Proxy classes be private now?

--
https://go-review.googlesource.com/21313
Gerrit-Reviewer: David Crawshaw <craw...@golang.org>
Gerrit-HasComments: No

Elias Naur (Gerrit)

unread,
Mar 31, 2016, 3:58:12 AM3/31/16
to David Crawshaw, golang-co...@googlegroups.com
Reviewers: David Crawshaw

Elias Naur uploaded a new patch set:
https://go-review.googlesource.com/21313

mobile/bind: don't force Java classes to extend stub classes

Requiring user code to extend Go interface Stubs to be able to pass
Java objects to Go is clumsy and use up the single extend slot.
Instead, support (and encourage) java classes that implement
translated Go interface directly. This is similar to how ObjC works.

The stub classes are now gone, and users of gobind Java APIs need
to update their code to implement interfaces directly.

Change-Id: I880bb7c8e89d3c21210b2ab2c85ced8d7859ff48
---
M bind/genjava.go
M bind/java/Seq.java
M bind/java/SeqBench.java
M bind/java/SeqTest.java
M bind/java/seq_android.c.support
M bind/testdata/ignore.java.golden
M bind/testdata/interfaces.java.golden
M bind/testdata/issue10788.java.golden
M bind/testdata/issue12328.java.golden
M bind/testdata/issue12403.java.golden
M bind/testdata/structs.java.golden
M bind/testdata/vars.java.golden
M cmd/gobind/doc.go
13 files changed, 151 insertions(+), 337 deletions(-)

Elias Naur (Gerrit)

unread,
Mar 31, 2016, 3:59:09 AM3/31/16
to David Crawshaw, golang-co...@googlegroups.com
Reviewers: David Crawshaw

Elias Naur uploaded a new patch set:
https://go-review.googlesource.com/21313

mobile/bind: don't force Java classes to extend stub classes

Requiring user code to extend Go interface Stubs to be able to pass
Java objects to Go is clumsy and use up the single extend slot.
Instead, support (and enforce) java classes to implement translated
Go interface directly. This is similar to how ObjC works.

The stub classes are now gone, and users of gobind Java APIs need
to update their code to implement interfaces directly.

Change-Id: I880bb7c8e89d3c21210b2ab2c85ced8d7859ff48
---
M bind/genjava.go
M bind/java/Seq.java
M bind/java/SeqBench.java
M bind/java/SeqTest.java
M bind/java/seq_android.c.support
M bind/testdata/ignore.java.golden
M bind/testdata/interfaces.java.golden
M bind/testdata/issue10788.java.golden
M bind/testdata/issue12328.java.golden
M bind/testdata/issue12403.java.golden
M bind/testdata/structs.java.golden
M bind/testdata/vars.java.golden
M cmd/gobind/doc.go

Elias Naur (Gerrit)

unread,
Mar 31, 2016, 3:59:47 AM3/31/16
to golang-...@googlegroups.com, David Crawshaw, golang-co...@googlegroups.com
Elias Naur has submitted this change and it was merged.

mobile/bind: don't force Java classes to extend stub classes

Requiring user code to extend Go interface Stubs to be able to pass
Java objects to Go is clumsy and use up the single extend slot.
Instead, support (and enforce) java classes to implement translated
Go interface directly. This is similar to how ObjC works.

The stub classes are now gone, and users of gobind Java APIs need
to update their code to implement interfaces directly.

Change-Id: I880bb7c8e89d3c21210b2ab2c85ced8d7859ff48
Reviewed-on: https://go-review.googlesource.com/21313
Reviewed-by: David Crawshaw <craw...@golang.org>
---
M bind/genjava.go
M bind/java/Seq.java
M bind/java/SeqBench.java
M bind/java/SeqTest.java
M bind/java/seq_android.c.support
M bind/testdata/ignore.java.golden
M bind/testdata/interfaces.java.golden
M bind/testdata/issue10788.java.golden
M bind/testdata/issue12328.java.golden
M bind/testdata/issue12403.java.golden
M bind/testdata/structs.java.golden
M bind/testdata/vars.java.golden
M cmd/gobind/doc.go
13 files changed, 151 insertions(+), 337 deletions(-)

Approvals:
David Crawshaw: Looks good to me, approved


--
https://go-review.googlesource.com/21313
Gerrit-Reviewer: David Crawshaw <craw...@golang.org>
Gerrit-Reviewer: Elias Naur <elias...@gmail.com>

Elias Naur (Gerrit)

unread,
Mar 31, 2016, 4:01:21 AM3/31/16
to David Crawshaw, golang-co...@googlegroups.com
Elias Naur has posted comments on this change.

mobile/bind: don't force Java classes to extend stub classes

Patch Set 6:

> Very nice.
>
> I don't think backwards compatibility is too important, no promise
> of stability has been made yet. If you want to remove the
> deprecated generated classes, go ahead.
>

Cool, I removed the Stub classes in the submitted CL.

> Could the generated Proxy classes be private now?

Yes, but not trivially, so I'll postpone that for another CL. Apparently,
classes inside interfaces are implicitly public and can't be declared
otherwise.

--
https://go-review.googlesource.com/21313
Gerrit-Reviewer: David Crawshaw <craw...@golang.org>
Gerrit-Reviewer: Elias Naur <elias...@gmail.com>
Gerrit-HasComments: No
Reply all
Reply to author
Forward
0 new messages