bind/java: initialize seq machinery from Java

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.

Fixes golang/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 commit is contained in:
David Crawshaw 2015-05-21 12:32:58 -04:00
parent d2634ce9c5
commit 64c20ce93d
5 changed files with 16 additions and 43 deletions

View File

@ -66,6 +66,12 @@ public class Seq {
return tracker.get(refnum);
}
static {
initSeq();
}
static native void initSeq();
// Informs the Go ref tracker that Java is done with this ref.
static native void destroyRef(int refnum);

View File

@ -12,5 +12,7 @@ package java
// Init initializes communication with Java.
// Typically called from the Start callback in app.Run.
func Init() {
initSeq()
close(running)
}
var running = make(chan struct{})

View File

@ -1,9 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !android
package java
func initSeq() {}

View File

@ -167,12 +167,8 @@ static void describe_exception(JNIEnv* env) {
}
}
// find_class_fn finds a class with the given name using the app class loader.
// It is implemented in the app package and is initialized during the init_seq call.
static jclass (*find_class_fn)(JNIEnv*, const char*);
static jfieldID find_field(JNIEnv *env, const char *class_name, const char *field_name, const char *field_type) {
jclass clazz = find_class_fn(env, class_name);
jclass clazz = (*env)->FindClass(env, class_name);
if (clazz == NULL) {
describe_exception(env);
LOG_FATAL("cannot find %s", class_name);
@ -188,7 +184,7 @@ static jfieldID find_field(JNIEnv *env, const char *class_name, const char *fiel
}
static jclass find_class(JNIEnv *env, const char *class_name) {
jclass clazz = find_class_fn(env, class_name);
jclass clazz = (*env)->FindClass(env, class_name);
if (clazz == NULL) {
describe_exception(env);
LOG_FATAL("cannot find %s", class_name);
@ -197,19 +193,8 @@ static jclass find_class(JNIEnv *env, const char *class_name) {
return (*env)->NewGlobalRef(env, clazz);
}
void init_seq(void *javavm, void *classfinder) {
JavaVM *vm = (JavaVM*)javavm;
find_class_fn = (jclass (*)(JNIEnv*, const char*))classfinder;
JNIEnv *env;
int res = (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
if ((*vm)->AttachCurrentThread(vm, &env, NULL) != JNI_OK) {
LOG_FATAL("cannot attach to current_vm");
}
} else if (res != JNI_OK) {
LOG_FATAL("bad vm env: %d", res);
}
JNIEXPORT void JNICALL
Java_go_Seq_initSeq(JNIEnv *env, jclass clazz) {
memptr_id = find_field(env, "go/Seq", "memptr", "J");
receive_refnum_id = find_field(env, "go/Seq$Receive", "refnum", "I");
receive_handle_id = find_field(env, "go/Seq$Receive", "handle", "I");
@ -219,14 +204,10 @@ void init_seq(void *javavm, void *classfinder) {
// its class info, because finding the jbyteArray class ("[B") using
// find_class_fn or JNIEnv's FindClass does not work on android-L.
jbyteArray a = (*env)->NewByteArray(env, 0);
jclass clazz = (*env)->GetObjectClass(env, a);
jbytearray_clazz = (*env)->NewGlobalRef(env, clazz);
jclass bclazz = (*env)->GetObjectClass(env, a);
jbytearray_clazz = (*env)->NewGlobalRef(env, bclazz);
LOG_INFO("loaded go/Seq");
if (res == JNI_EDETACHED) {
(*vm)->DetachCurrentThread(vm);
}
}
JNIEXPORT void JNICALL

View File

@ -15,7 +15,6 @@ import (
"sync"
"unsafe"
"golang.org/x/mobile/app"
"golang.org/x/mobile/bind/seq"
)
@ -26,6 +25,7 @@ const debug = false
// Send is called by Java to send a request to run a Go function.
//export Send
func Send(descriptor string, code int, req *C.uint8_t, reqlen C.size_t, res **C.uint8_t, reslen *C.size_t) {
<-running
fn := seq.Registry[descriptor][code]
if fn == nil {
panic(fmt.Sprintf("invalid descriptor(%s) and code(0x%x)", descriptor, code))
@ -78,13 +78,6 @@ func init() {
res.out = make(map[int32]*seq.Buffer)
}
func initSeq() {
vm := app.GetConfig().JavaVM()
classFinder := app.GetConfig().ClassFinder()
C.init_seq(vm, classFinder)
}
func seqToBuf(bufptr **C.uint8_t, lenptr *C.size_t, buf *seq.Buffer) {
if debug {
fmt.Printf("seqToBuf tag 1, len(buf.Data)=%d, *lenptr=%d\n", len(buf.Data), *lenptr)