From 64c20ce93dd0f5428191a509374ee38477ecfb2e Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Thu, 21 May 2015 12:32:58 -0400 Subject: [PATCH] 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 Reviewed-by: Hyang-Ah Hana Kim --- bind/java/Seq.java | 6 ++++++ bind/java/doc.go | 4 +++- bind/java/noimpl.go | 9 --------- bind/java/seq_android.c | 31 ++++++------------------------- bind/java/seq_android.go | 9 +-------- 5 files changed, 16 insertions(+), 43 deletions(-) delete mode 100644 bind/java/noimpl.go diff --git a/bind/java/Seq.java b/bind/java/Seq.java index 028b2f2..959ddd5 100644 --- a/bind/java/Seq.java +++ b/bind/java/Seq.java @@ -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); diff --git a/bind/java/doc.go b/bind/java/doc.go index 77c4c26..b846381 100644 --- a/bind/java/doc.go +++ b/bind/java/doc.go @@ -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{}) diff --git a/bind/java/noimpl.go b/bind/java/noimpl.go deleted file mode 100644 index c123645..0000000 --- a/bind/java/noimpl.go +++ /dev/null @@ -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() {} diff --git a/bind/java/seq_android.c b/bind/java/seq_android.c index 29cefc9..3a3f067 100644 --- a/bind/java/seq_android.c +++ b/bind/java/seq_android.c @@ -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 diff --git a/bind/java/seq_android.go b/bind/java/seq_android.go index 1d19bde..6b0145b 100644 --- a/bind/java/seq_android.go +++ b/bind/java/seq_android.go @@ -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)