2
0
mirror of synced 2025-02-23 06:48:15 +00:00

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 <crawshaw@golang.org>
This commit is contained in:
Elias Naur 2016-03-30 19:02:17 +02:00
parent 07a529f836
commit 5e11c20fc0
13 changed files with 151 additions and 337 deletions

View File

@ -27,7 +27,7 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
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 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
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) {
@ -136,20 +137,8 @@ func (g *javaGen) genStruct(obj *types.TypeName, T *types.Struct) {
g.Printf("}\n\n")
}
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")
}
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,10 +150,13 @@ func (g *javaGen) genInterface(iface interfaceInfo) {
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
for _, m := range iface.summary.callable {
if !g.isSigSupported(m.Type()) {
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name())
@ -172,14 +164,8 @@ func (g *javaGen) genInterface(iface interfaceInfo) {
}
g.genFuncSignature(m, false, true)
}
if methodSigErr {
return // skip stub generation, more of the same errors
}
if iface.summary.implementable {
g.genInterfaceStub(iface.obj, iface.t)
}
g.Printf("\n")
g.Printf(javaProxyPreamble, iface.obj.Name())
g.Indent()
@ -1099,12 +1085,8 @@ func (g *javaGen) genJava() error {
}
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.

View File

@ -5,6 +5,7 @@
package go;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.logging.Logger;
// Seq is a sequence of machine-dependent encoded values.
@ -15,7 +16,7 @@ public class Seq {
// 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 @@ public class Seq {
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 @@ public class Seq {
// 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 @@ public class Seq {
// 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;
@ -124,6 +124,14 @@ public class Seq {
}
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++;
}
}
static final RefTracker tracker = new RefTracker();
@ -142,32 +150,44 @@ public class Seq {
// 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 IdentityHashMap<Object, Integer> javaRefs = new IdentityHashMap<>();
// 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,21 +212,10 @@ public class Seq {
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.
// It may be the first time we have seen the Go object.
//

View File

@ -17,12 +17,12 @@ import go.benchmark.Benchmark;
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();

View File

@ -216,7 +216,7 @@ public class SeqTest extends InstrumentationTestCase {
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 @@ public class SeqTest extends InstrumentationTestCase {
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 @@ public class SeqTest extends InstrumentationTestCase {
//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 class SeqTest extends InstrumentationTestCase {
}
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 class SeqTest extends InstrumentationTestCase {
}
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 class SeqTest extends InstrumentationTestCase {
}
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 class SeqTest extends InstrumentationTestCase {
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;
}

View File

@ -307,7 +307,7 @@ Java_go_Seq_init(JNIEnv *env, jclass clazz) {
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 @@ Java_go_Seq_init(JNIEnv *env, jclass clazz) {
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");
}

View File

@ -19,12 +19,8 @@ public abstract class Ignore {
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,14 @@ public abstract class Ignore {
}
}
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; }
}
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

View File

@ -19,167 +19,83 @@ public abstract class Interfaces {
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; }
}
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; }
}
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; }
}
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; }
}
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; }
}
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; }
}
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);
}

View File

@ -19,12 +19,8 @@ public abstract class Issue10788 {
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,12 @@ public abstract class Issue10788 {
}
}
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; }
}
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);

View File

@ -19,12 +19,8 @@ public abstract class Issue12328 {
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);

View File

@ -19,25 +19,12 @@ public abstract class Issue12403 {
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; }
}
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;

View File

@ -19,12 +19,8 @@ public abstract class Structs {
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 abstract class Structs {
}
}
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,11 @@ public abstract class Structs {
}
}
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; }
}
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();
}

View File

@ -19,12 +19,8 @@ public abstract class Vars {
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,10 @@ public abstract class Vars {
}
}
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 {
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); }
}
}

View File

@ -90,27 +90,23 @@ For a Go interface:
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 {
...
}
...
}
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 @@ of G, then the language bindings on each side must keep G and J live
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