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:
parent
d2634ce9c5
commit
64c20ce93d
|
@ -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);
|
||||
|
||||
|
|
|
@ -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{})
|
||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue