When a Java stub object instance is passed into Go, and then Go's garbage collection runs, and then the same Java object is passed into Go again, an exception is thrown in go.Seq.java and the Android app crashes.
Build using gomobile bind and import resulting AAR into an Android Studio project
Sample code follows; based on golang.org/x/mobile/example/libhello/hi. This is a contrived example with an explicit GC() call, but I've also hit this exception -- eventually -- in real code.
As best as I can tell, the problem may be a lifetime mismatch in the go.Seq.Ref reference counting. The constructor of the Stub creates a reference. When the Java object reference is passed to Go, the reference is scheduled for deletion using runtime.SetFinalizer here. The SetFinalizer handler signals the Java reference manager to delete the reference. But since the reference is only added in the Java Stub object constructor, there's no valid reference when the Java object is used again after the SetFinalizer signal and the exception will be thrown.
Summary
When a Java stub object instance is passed into Go, and then Go's garbage collection runs, and then the same Java object is passed into Go again, an exception is thrown in go.Seq.java and the Android app crashes.
Test setup
gomobile bind
and import resulting AAR into an Android Studio projectAs best as I can tell, the problem may be a lifetime mismatch in the go.Seq.Ref reference counting. The constructor of the Stub creates a reference. When the Java object reference is passed to Go, the reference is scheduled for deletion using runtime.SetFinalizer here. The SetFinalizer handler signals the Java reference manager to delete the reference. But since the reference is only added in the Java Stub object constructor, there's no valid reference when the Java object is used again after the SetFinalizer signal and the exception will be thrown.
The docs on passing foreign language objects to Go don't indicate that this reuse of a Java Stub object is not supported.
One workaround is to create a new, proxy Java object each time you wish to pass the same long-lived Java object into Go.
Exception
Sample Go package
Sample Android app using the Go package