There was a discussion a year ago about making methods and types
lowercase in ObjC (https://github.com/golang/go/issues/12889),
which was done (https://go-review.googlesource.com/#/c/15780/),
alas the suggested Java lower casing was never addressed.
This CL converts all generated Java methods to lower case.
Change-Id: Ia2f28519bc59362877881636109ddfc651b24960
Reviewed-on: https://go-review.googlesource.com/28494
Reviewed-by: Elias Naur <elias.naur@gmail.com>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Before this CL, generated Java classes or interfaces were inner
classes to the top package class. That is both unnecessary and creates
ugly class names. Instead, move every generated class and interface to its
own package level class.
NOTE: This is a backwards incompatible change and requires every client
of gomobile APIs to be updated to leave out the package class in the
type names. For example, the Go type
package pkg
type S struct {
}
now generates (with the default java package name go) a Java class named
go.pkg.S. The name before this CL was go.pkg.Pkg.S.
Also, change the custom java package to specify the package prefix and
not the full package as before. This is an unfortunate change needed
to avoid name clashes between two bound packages. On the plus side,
the change brings the custom package case closer to the default behaviour,
which is a commen prefix, "go.", and a distinct java package for every
Go package bound.
Change-Id: Iadfaad56e101d1caf7e2a05006f4d384859a20fe
Reviewed-on: https://go-review.googlesource.com/27436
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Gobind uses strings for passing errors across the language barrier.
However, since Gobind doesn't have a concept of a nil string, it
can't separate an empty native string from a nil string.
In turn, that means that empty errors, exceptions or NSError * with
an empty description are treated as no error. With ObjC, empty errors
are replaced with a default string to workaround the issue, while
with Java empty errors are silently ignored.
Fix this by replacing strings with actual error objects, wrapping
the Go error, Java Throwable or ObjC NSError *, and letting the
existing bind machinery take care of passing the references across.
It's a large change for a small corner case, but I believe objects
are a better fit for exception that strings. Error objects also
naturally leads to future additions, for example accessing the
exception class name or chained exception.
Change-Id: Ie03b47cafcb231ad1e12a80195693fa7459c6265
Reviewed-on: https://go-review.googlesource.com/24100
Reviewed-by: David Crawshaw <crawshaw@golang.org>
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>
Each side of the language barrier maintains a map of reference numbers
to objects. Each entry has a reference count that exactly matches
the number of active proxy objects on the other side. When a reference
crosses the barrier, the count is incremented and when a proxy finalizer
is run, the count is decremented. If the count reaches 0, the reference
number and its object are removed from the map.
There is a possibility that a reference number is passed to the other
side, and the last proxy is then immediately garbage collected and
finalized. The reference counter then reaches 0 before the other side has
converted the reference number to its object, crashing the program.
This is possible in both Go/Java/ObjC but is most likely to happen in
ObjC because its own automatic reference count runtime frees objects
as soon as they are statically never referenced again.
Fix the race by always incrementing the reference count before sending
a reference across the barrier. When converting the reference back into
an object on the other side, decrement the counter again.
Only the new ObjC test fails without this fix, but I left the Java
counterpart in for good measure.
Change-Id: I92743aabec275b4a5b82b952052e7e284872ce02
Reviewed-on: https://go-review.googlesource.com/21311
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The seq serialization machinery is a historic artifact from when Go
mobile code had to run in a separate process. Now that Go code is running
in-process, replace the explicit serialization with direct calls and pass
arguments on the stack.
The benefits are a much smaller bind runtime, much less garbage (and, in
Java, fewer objects with finalizers), less argument copying, and faster
cross-language calls.
The cost is a more complex generator, because some of the work from the
bind runtime is moved to generated code. Generated code now handles
conversion between Go and Java/ObjC types, multiple return values and memory
management of byte slice and string arguments.
To overcome the lack of calling C code between Go packages, all bound
packages now end up in the same (fake) package, "gomobile_bind", instead of
separate packages (go_<pkgname>). To avoid name clashes, the package name is
added as a prefix to generated functions and types.
Also, don't copy byte arrays passed to Go, saving call time and
allowing read([]byte)-style interfaces to foreign callers (#12113).
Finally, add support for nil interfaces and struct pointers to objc.
This is a large CL, but most of the changes stem from changing testdata.
The full benchcmp output on the CL/20095 benchmarks on my Nexus 5 is
reproduced below. Note that the savings for the JavaSlice* benchmarks are
skewed because byte slices are no longer copied before passing them to Go.
benchmark old ns/op new ns/op delta
BenchmarkJavaEmpty 26.0 19.0 -26.92%
BenchmarkJavaEmptyDirect 23.0 22.0 -4.35%
BenchmarkJavaNoargs 7685 2339 -69.56%
BenchmarkJavaNoargsDirect 17405 8041 -53.80%
BenchmarkJavaOnearg 26887 2366 -91.20%
BenchmarkJavaOneargDirect 34266 7910 -76.92%
BenchmarkJavaOneret 38325 2245 -94.14%
BenchmarkJavaOneretDirect 46265 7708 -83.34%
BenchmarkJavaManyargs 41720 2535 -93.92%
BenchmarkJavaManyargsDirect 51026 8373 -83.59%
BenchmarkJavaRefjava 38139 21260 -44.26%
BenchmarkJavaRefjavaDirect 42706 28150 -34.08%
BenchmarkJavaRefgo 34403 6843 -80.11%
BenchmarkJavaRefgoDirect 40193 16582 -58.74%
BenchmarkJavaStringShort 32366 9323 -71.20%
BenchmarkJavaStringShortDirect 41973 19118 -54.45%
BenchmarkJavaStringLong 127879 94420 -26.16%
BenchmarkJavaStringLongDirect 133776 114760 -14.21%
BenchmarkJavaStringShortUnicode 32562 9221 -71.68%
BenchmarkJavaStringShortUnicodeDirect 41464 19094 -53.95%
BenchmarkJavaStringLongUnicode 131015 89401 -31.76%
BenchmarkJavaStringLongUnicodeDirect 134130 90786 -32.31%
BenchmarkJavaSliceShort 42462 7538 -82.25%
BenchmarkJavaSliceShortDirect 52940 17017 -67.86%
BenchmarkJavaSliceLong 138391 8466 -93.88%
BenchmarkJavaSliceLongDirect 205804 15666 -92.39%
BenchmarkGoEmpty 3.00 3.00 +0.00%
BenchmarkGoEmptyDirect 3.00 3.00 +0.00%
BenchmarkGoNoarg 40342 13716 -66.00%
BenchmarkGoNoargDirect 46691 13569 -70.94%
BenchmarkGoOnearg 43529 13757 -68.40%
BenchmarkGoOneargDirect 44867 14078 -68.62%
BenchmarkGoOneret 45456 13559 -70.17%
BenchmarkGoOneretDirect 44694 13442 -69.92%
BenchmarkGoRefjava 55111 28071 -49.06%
BenchmarkGoRefjavaDirect 60883 26872 -55.86%
BenchmarkGoRefgo 57038 29223 -48.77%
BenchmarkGoRefgoDirect 56153 27812 -50.47%
BenchmarkGoManyargs 67967 17398 -74.40%
BenchmarkGoManyargsDirect 60617 16998 -71.96%
BenchmarkGoStringShort 57538 22600 -60.72%
BenchmarkGoStringShortDirect 52627 22704 -56.86%
BenchmarkGoStringLong 128485 52530 -59.12%
BenchmarkGoStringLongDirect 138377 52079 -62.36%
BenchmarkGoStringShortUnicode 57062 22994 -59.70%
BenchmarkGoStringShortUnicodeDirect 62563 22938 -63.34%
BenchmarkGoStringLongUnicode 139913 55553 -60.29%
BenchmarkGoStringLongUnicodeDirect 150863 57791 -61.69%
BenchmarkGoSliceShort 59279 20215 -65.90%
BenchmarkGoSliceShortDirect 60160 21136 -64.87%
BenchmarkGoSliceLong 411225 301870 -26.59%
BenchmarkGoSliceLongDirect 399029 298915 -25.09%
Fixesgolang/go#12619Fixesgolang/go#12113Fixesgolang/go#13033
Change-Id: I2b45e9e98a1248e3c23a5137f775f7364908bec7
Reviewed-on: https://go-review.googlesource.com/19821
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
RefMap tracks its number of live Ref instances in the 'live' member.
However, when a reference was removed and later added, 'live' wasn't
updated accordingly. Fix and add a test.
Change-Id: I806e17ea0319d76db4d07b5f8d9107b146ee80db
Reviewed-on: https://go-review.googlesource.com/19975
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The Seq Java class has a special case for null references. Expand
the special case to Go so that null references from Java are properly
translated to nil.
Fixesgolang/go#14228
Change-Id: I915d1f843c9db299d6910480f6d10dae0121a3b4
Reviewed-on: https://go-review.googlesource.com/19460
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Java methods from Go are run on a thread pool managed on the Java side,
to avoid the complexities of getting Go threads to play along with the
Android JVM. However, for call stacks that contain a Java->Go->Java
chain, this behaviour confuses Java code sensitive to specific threads
if the Go->Java call is executed on an arbitrary thread from the pool.
For example, most Android UI changes must happen on the single UI
thread.
Replace the thread pool with direct calls to mimic ObjC<->Go and
Java->Go calls. Threads not already attached to the JVM are attached.
Introduce a thread local variable to detach such threads at thread exit.
Change-Id: I8cb65803c9278666ae77a0c7a65dc2d9c7e739e1
Reviewed-on: https://go-review.googlesource.com/19334
Reviewed-by: David Crawshaw <crawshaw@golang.org>
An inspection of the RefTracker inc and dec methods suggests
that a particular Java Stub instance is included in the javaObjs
map if and only if its reference count, refcnt, is larger than zero.
A newly created reference created by RefTracker.createRef has zero
refcnt but was also inserted in the javaObjs map, violating the invariant.
Fix that by not inserting new references in javaObjs. Without the fix
a Stub instance that were never passed to Go would leak, along with
any other instances it referenced, transitively.
This fixes a Java reference tracking problem, I have not verified if
the same problem applies to the Go and ObjC sides of the Seq machinery.
Change-Id: I3ede90d5258630bc837fe61bba850df222d09a26
Reviewed-on: https://go-review.googlesource.com/19261
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This removes the last dependency on an Android class in the running
gobind code. (Tests still need some work before they will run on the
desktop.)
Change-Id: I49bfb545d4587c6f430c0938fa1ca4d513b56d77
Reviewed-on: https://go-review.googlesource.com/17252
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The aim of the RefTracker is to "... pin Java objects so
they don't get GCed while the only reference to them is
held by Go code." But in the case of null objects there is
nothing to GC. Therefore we do return a single Ref which
contains a null object, but we ignore the logic that is used
to pin for GC purposes.
Change-Id: If3771ec0180d09485963c3297abccb39a1a8d9ab
Reviewed-on: https://go-review.googlesource.com/13647
Reviewed-by: David Crawshaw <crawshaw@golang.org>
non-varargs call of varargs method with inexact argument type for last
parameter
Change-Id: I7623951c365b8cf899a17ee784c8d4f3b4bdb198
Reviewed-on: https://go-review.googlesource.com/12528
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This is done by moving app.Context to internal/mobileinit,
introducing mobileinit.SetCurrentContext and,
making bind/java depend on it.
TODO: check gomobile bind's proguard rule - context lookup
was implemented through reflection on android.app.AppGlobals class.
Change-Id: Ieb6ad503eeef8c2c1c5836a21c667938c5a701a2
Reviewed-on: https://go-review.googlesource.com/12279
Reviewed-by: David Crawshaw <crawshaw@golang.org>
The goal here is to remove several inconsistencies between
-target=android and -target=ios support, along with making the flow
of the command follow the path you might expect given a certain set
of flags, and preparing for `gomobile bind` support of ios. In
particular, building non-main packages now works with both targets
and the initialization of global build state is clearer.
The reorg also is designed around an nm trick I thought of
yesterday to do better package import scanning without a slow
all-file scan. This will give better detection of x/mobile/app and
x/mobile/exp/audio/al packages. There's a TODO about it, and I'll do
it in a future CL.
Tested with:
go test golang.org/x/mobile/cmd/gomobile
gomobile init
gomobile bind golang.org/x/mobile/asset
go test golang.org/x/mobile/bind/java
gomobile build -target=ios golang.org/x/mobile/example/basic
gomobile build -target=ios golang.org/x/mobile/gl
gomobile build -target=android golang.org/x/mobile/gl
gomobile build -target=android golang.org/x/mobile/example/basic
(Along with manual testing of basic on an android device.)
That might make a pretty good _test.go.
Change-Id: I41230008c3c15db25a11c33b9eaca4abada9f411
Reviewed-on: https://go-review.googlesource.com/12051
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Historically, the app package implemented Go runtime initialization.
This was convoluted, so the package was used both by all-Go apps
(currently based on Android's NativeActivity) and bind-based apps.
With Go 1.5 we have -buildmode=c-shared, which does a lot of the work
of the old app package. That code was removed a while back, but both
all-Go and gobind-based apps still used package app. The intermingled
initialization processes led to some strange states.
This CL separates gobind-based apps completely from the app package.
As part of that users are now expected to use System.loadLibrary
themselves. (A future CL may want to make the loadLibrary call part
of the .aar generated by gomobile bind.)
Delete the libhello example, which has been replaced by gomobile bind,
which could do with its own example at some point. Also delete the
libhellojni example, which now has nothing to do with the x/mobile
repository.
Change-Id: I444397f246dbafe81e5c53532eb482c197d26f70
Reviewed-on: https://go-review.googlesource.com/11654
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
The gobind framework is supposed to use reference counting to
keep track of objects (e.g. pointer to a Go struct, interface
values) crossing the language boundary. This change fixes two bugs:
1) no reference counting on Java object: Previously, the lifetime
of a Java object was manages in the following way.
a. The Java object is pinned in an internal map (javaObjs) when it's
constructed.
b. When Go receives the reference to the Java object, it creates a
proxy object and sets a finalizer on it. The finalizer signals Java
to unpin the Java object (remove from the javaObjs map).
c. The javaObjs map is also used to identify the Java object when
Go asks to invoke a method on it later.
When the same Java object is sent to Java more than once, and the
finalizer (b) runs after the first use, the second use of the Java
object can cause the crash described in golang/go#10933.
This change fixes the bug by reference counting the Java object.
Java side pins the Java object and increments the refcount whenever it
sees the object sent to Go (in Seq.writeRef). When the Go proxy
object's finalizer runs, the refcount is decremented. When the refcount
becomes 0, the object gets unpined.
2) race in Go object lifetime management: Pinning on a Go object
has been done when the Go object is sent to Java but the Go object
is not in the pinned object map yet. (bind/seq.WriteGoRef).
Unpinning the object occurs when Java finds there are no proxy objects
on its side. For this, Java maintains a reference count map (goObjs).
When the refcount becomes zero, Java notifies Go so the object is
unpinned. Here is a race case:
a. Java has a proxy object for a Go object.
b. Go is preparing for sending the same Go object. seq.WriteGoRef
notices the corresponding entry in the pinned object map already,
and returns. The remaining work for sending the object continues.
c. The proxy object in Java finalizes and triggers deletion of the
object from the pinned object map.
d. The remaining work for (b) completes and Java creates a new proxy
object. When a method is called for the Go object, the Go object is
already removed from the object map on Go side and maybe already GC'd.
This change fixes it by converting the pinned object map to reference
counter map maintained in Go. The counter increments for each
seq.WriteGoRef call. The finalizer of the proxy object in Java causes
a decrement of the counter.
Fixesgolang/go#10933.
Renables the skipped testJavaRefGC.
Change-Id: I0992e002b1050b6183689e5ab821e058adbb420f
Reviewed-on: https://go-review.googlesource.com/10638
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This ensures that the java bindings are ready before any calls are
made by user code. As a bonus, the JNIEnv* is from the Seq class so I
believe no tricks are required to find the right class loader.
Fixesgolang/go#10903.
Change-Id: I33b3b39cef6cc2da36e271de882ba8d26610ea34
Reviewed-on: https://go-review.googlesource.com/10296
Reviewed-by: Elias Naur <elias.naur@gmail.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This is to enable more flexible encoding/decoding of Go string.
For Java, we use UTF16 to be compatible with java string.
For other languages, we will want other way to represent a string.
Change-Id: Iccd53e2eea18d37636c3c619d06cb473facef0cd
Reviewed-on: https://go-review.googlesource.com/8628
Reviewed-by: David Crawshaw <crawshaw@golang.org>