@@ -16,7 +16,6 @@ extern "C" {
1616static JavaVM *gJvm = nullptr ;
1717static jobject gClassLoader ;
1818static jmethodID gFindClassMethod ;
19- static JNIEnv *gCurEnv = nullptr ;
2019static pthread_key_t detachKey = 0 ;
2120
2221typedef void (*NativeMethodCallback)(
@@ -36,45 +35,48 @@ static std::map<void *, jobject> callbackObjCache;
3635static std::map<jlong, std::map<std::string, NativeMethodCallback>> callbackManagerCache;
3736static std::map<jlong, void *> targetCache;
3837
39- JNIEnv *getEnv () {
40- JNIEnv *env;
41- int status = gJvm ->GetEnv ((void **) &env, JNI_VERSION_1_6);
42- if (status < 0 ) {
43- status = gJvm ->AttachCurrentThread (&env, NULL );
44- if (status < 0 ) {
45- return nullptr ;
46- }
47- }
48- return env;
49- }
5038
5139void detachThreadDestructor (void * arg) {
5240 NSLog (" detach from current thread" );
5341 gJvm ->DetachCurrentThread ();
5442 detachKey = 0 ;
5543}
5644
57- void attachThread () {
45+ JNIEnv *getEnv () {
46+ if (gJvm == nullptr ) {
47+ return nullptr ;
48+ }
49+
5850 if (detachKey == 0 ) {
59- NSLog (" attach to current thread" );
6051 pthread_key_create (&detachKey, detachThreadDestructor);
61- gJvm ->AttachCurrentThread (&gCurEnv , NULL );
62- pthread_setspecific (detachKey, nullptr );
52+ }
53+ JNIEnv *env;
54+ jint ret = gJvm ->GetEnv ((void **) &env, JNI_VERSION_1_6);
55+
56+ switch (ret) {
57+ case JNI_OK:
58+ return env;
59+ case JNI_EDETACHED:
60+ NSLog (" attach to current thread" );
61+ gJvm ->AttachCurrentThread (&env, NULL );
62+ return env;
63+ default :
64+ NSLog (" fail to get env" );
65+ return nullptr ;
6366 }
6467}
6568
6669JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *pjvm, void *reserved) {
6770 NSLog (" JNI_OnLoad" );
6871 gJvm = pjvm; // cache the JavaVM pointer
69- gCurEnv = getEnv ();
7072 // replace with one of your classes in the line below
71- auto randomClass = gCurEnv ->FindClass (" com/dartnative/dart_native/DartNativePlugin" );
72- jclass classClass = gCurEnv ->GetObjectClass (randomClass);
73- auto classLoaderClass = gCurEnv ->FindClass (" java/lang/ClassLoader" );
74- auto getClassLoaderMethod = gCurEnv ->GetMethodID (classClass, " getClassLoader" ,
73+ auto randomClass = getEnv () ->FindClass (" com/dartnative/dart_native/DartNativePlugin" );
74+ jclass classClass = getEnv () ->GetObjectClass (randomClass);
75+ auto classLoaderClass = getEnv () ->FindClass (" java/lang/ClassLoader" );
76+ auto getClassLoaderMethod = getEnv () ->GetMethodID (classClass, " getClassLoader" ,
7577 " ()Ljava/lang/ClassLoader;" );
76- gClassLoader = gCurEnv ->NewGlobalRef (gCurEnv ->CallObjectMethod (randomClass, getClassLoaderMethod));
77- gFindClassMethod = gCurEnv ->GetMethodID (classLoaderClass, " findClass" ,
78+ gClassLoader = getEnv () ->NewGlobalRef (getEnv () ->CallObjectMethod (randomClass, getClassLoaderMethod));
79+ gFindClassMethod = getEnv () ->GetMethodID (classLoaderClass, " findClass" ,
7880 " (Ljava/lang/String;)Ljava/lang/Class;" );
7981
8082 NSLog (" JNI_OnLoad finish" );
@@ -88,12 +90,11 @@ char *spliceChar(char *dest, char *src) {
8890 return result;
8991}
9092
91- char *generateSignature (char **argTypes) {
93+ char *generateSignature (char **argTypes, int argCount ) {
9294 char *signature = const_cast <char *>(" (" );
93- int argCount = 0 ;
9495 if (argTypes != nullptr )
9596 {
96- for (; *argTypes ; ++argTypes, ++argCount ) {
97+ for (int i = 0 ; i < argCount ; ++argTypes, i++ ) {
9798 char *templeSignature = spliceChar (signature, *argTypes);
9899 signature = templeSignature;
99100 free (templeSignature);
@@ -102,12 +103,12 @@ char *generateSignature(char **argTypes) {
102103 return spliceChar (signature, const_cast <char *>(" )" ));
103104}
104105
105- void fillArgs (void **args, char **argTypes, jvalue *argValues) {
106- for (jsize index (0 ); *argTypes ; ++args, ++index, ++argTypes) {
106+ void fillArgs (void **args, char **argTypes, jvalue *argValues, int argCount ) {
107+ for (jsize index (0 ); index < argCount ; ++args, ++index, ++argTypes) {
107108 char *argType = *argTypes;
108109 if (strlen (argType) > 1 ) {
109110 if (strcmp (argType, " Ljava/lang/String;" ) == 0 ) {
110- argValues[index].l = gCurEnv ->NewStringUTF ((char *)*args);
111+ argValues[index].l = getEnv () ->NewStringUTF ((char *)*args);
111112 }
112113 else {
113114 jobject object = callbackObjCache.count (*args) ? callbackObjCache[*args] : static_cast <jobject>(*args);
@@ -156,38 +157,34 @@ jclass findClass(JNIEnv *env, const char *name) {
156157 return nativeClass;
157158}
158159
159- jobject newObject (jclass cls, void **args, char **argTypes) {
160- char *signature = generateSignature (argTypes);
161- jvalue *argValues = new jvalue[strlen (signature) - 2 ];
162- if (strlen (signature) - 2 > 0 ) {
163- fillArgs (args, argTypes, argValues);
160+ jobject newObject (jclass cls, void **args, char **argTypes, int argCount ) {
161+ char *signature = generateSignature (argTypes, argCount );
162+ jvalue *argValues = new jvalue[argCount ];
163+ if (argCount > 0 ) {
164+ fillArgs (args, argTypes, argValues, argCount );
164165 }
165166 char *constructorSig = spliceChar (signature, const_cast <char *>(" V" ));
166- jmethodID constructor = gCurEnv ->GetMethodID (cls, " <init>" , constructorSig);
167- jobject newObj = gCurEnv ->NewObjectA (cls, constructor, argValues);
167+ jmethodID constructor = getEnv () ->GetMethodID (cls, " <init>" , constructorSig);
168+ jobject newObj = getEnv () ->NewObjectA (cls, constructor, argValues);
168169 free (argValues);
169170 free (constructorSig);
170171 return newObj;
171172}
172173
173- void *createTargetClass (char *targetClassName, void **args, char **argTypes) {
174- attachThread ();
175-
176- jclass cls = findClass (gCurEnv , targetClassName);
174+ void *createTargetClass (char *targetClassName, void **args, char **argTypes, int argCount) {
175+ jclass cls = findClass (getEnv (), targetClassName);
177176
178- jobject newObj = gCurEnv ->NewGlobalRef (newObject (cls, args, argTypes));
179- cache[newObj] = static_cast <jclass>(gCurEnv ->NewGlobalRef (cls));
177+ jobject newObj = getEnv () ->NewGlobalRef (newObject (cls, args, argTypes, argCount ));
178+ cache[newObj] = static_cast <jclass>(getEnv () ->NewGlobalRef (cls));
180179
181180 return newObj;
182181}
183182
184183
185184void releaseTargetClass (void *classPtr) {
186- attachThread ();
187-
188185 jobject object = static_cast <jobject>(classPtr);
189186 cache.erase (object);
190- gCurEnv ->DeleteGlobalRef (object);
187+ getEnv () ->DeleteGlobalRef (object);
191188}
192189
193190void retain (void *classPtr) {
@@ -211,71 +208,69 @@ void release(void *classPtr) {
211208 referenceCount[object] = count - 1 ;
212209}
213210
214- void *invokeNativeMethodNeo (void *classPtr, char *methodName, void **args, char **argTypes, char *returnType) {
211+ void *invokeNativeMethodNeo (void *classPtr, char *methodName, void **args, char **argTypes, int argCount, char *returnType) {
215212 void *nativeInvokeResult = nullptr ;
216213
217- attachThread ();
218214 jobject object = static_cast <jobject>(classPtr);
219215 jclass cls = cache[object];
220- char *signature = generateSignature (argTypes);
221- jvalue *argValues = new jvalue[strlen (signature) - 2 ];
222- if (( strlen (signature) - 2 ) > 0 ) {
223- fillArgs (args, argTypes, argValues);
216+ char *signature = generateSignature (argTypes, argCount );
217+ jvalue *argValues = new jvalue[argCount ];
218+ if (argCount > 0 ) {
219+ fillArgs (args, argTypes, argValues, argCount );
224220 }
225221 char *methodSignature = spliceChar (signature, returnType);
226- jmethodID method = gCurEnv ->GetMethodID (cls, methodName, methodSignature);
227- NSLog (" call method: %s descriptor: %s" , methodName, methodSignature);
222+ jmethodID method = getEnv ()->GetMethodID (cls, methodName, methodSignature);
228223
229224 if (strlen (returnType) > 1 ) {
230225 if (strcmp (returnType, " Ljava/lang/String;" ) == 0 ) {
231- jstring javaString = (jstring)gCurEnv ->CallObjectMethodA (object, method, argValues);
226+ jstring javaString = (jstring) getEnv () ->CallObjectMethodA (object, method, argValues);
232227 jboolean isCopy = JNI_FALSE;
233- nativeInvokeResult = (char *) gCurEnv ->GetStringUTFChars (javaString, &isCopy);
228+ nativeInvokeResult = (char *) getEnv () ->GetStringUTFChars (javaString, &isCopy);
234229 }
235230 else {
236- jobject obj = gCurEnv ->NewGlobalRef (gCurEnv ->CallObjectMethodA (object, method, argValues));
237- jclass objCls = gCurEnv ->GetObjectClass (obj);
231+ jobject obj = getEnv () ->NewGlobalRef (getEnv () ->CallObjectMethodA (object, method, argValues));
232+ jclass objCls = getEnv () ->GetObjectClass (obj);
238233 // store class value
239- cache[obj] = static_cast <jclass>(gCurEnv ->NewGlobalRef (objCls));
234+ cache[obj] = static_cast <jclass>(getEnv () ->NewGlobalRef (objCls));
240235 nativeInvokeResult = obj;
241236 }
242237 }
243238 else if (strcmp (returnType, " C" ) == 0 ) {
244- auto nativeChar = gCurEnv ->CallCharMethodA (object, method, argValues);
239+ auto nativeChar = getEnv () ->CallCharMethodA (object, method, argValues);
245240 nativeInvokeResult = (void *) nativeChar;
246241 }
247242 else if (strcmp (returnType, " I" ) == 0 ) {
248- auto nativeInt = gCurEnv ->CallIntMethodA (object, method, argValues);
243+ auto nativeInt = getEnv () ->CallIntMethodA (object, method, argValues);
249244 nativeInvokeResult = (void *) nativeInt;
250245 }
251246 else if (strcmp (returnType, " D" ) == 0 ) {
252- auto nativeDouble = gCurEnv ->CallDoubleMethodA (object, method, argValues);
247+ auto nativeDouble = getEnv () ->CallDoubleMethodA (object, method, argValues);
253248 double cDouble = (double ) nativeDouble;
254249 memcpy (&nativeInvokeResult, &cDouble, sizeof (double ));
255250 }
256251 else if (strcmp (returnType, " F" ) == 0 ) {
257- auto nativeDouble = gCurEnv ->CallFloatMethodA (object, method, argValues);
252+ auto nativeDouble = getEnv () ->CallFloatMethodA (object, method, argValues);
258253 float cDouble = (float ) nativeDouble;
259254 memcpy (&nativeInvokeResult, &cDouble, sizeof (float ));
260255 }
261256 else if (strcmp (returnType, " B" ) == 0 ) {
262- auto nativeByte = gCurEnv ->CallByteMethodA (object, method, argValues);
257+ auto nativeByte = getEnv () ->CallByteMethodA (object, method, argValues);
263258 nativeInvokeResult = (void *) nativeByte;
264259 }
265260 else if (strcmp (returnType, " S" ) == 0 ) {
266- auto nativeShort = gCurEnv ->CallShortMethodA (object, method, argValues);
261+ auto nativeShort = getEnv () ->CallShortMethodA (object, method, argValues);
267262 nativeInvokeResult = (void *) nativeShort;
268263 }
269264 else if (strcmp (returnType, " J" ) == 0 ) {
270- auto nativeLong = gCurEnv ->CallLongMethodA (object, method, argValues);
265+ auto nativeLong = getEnv () ->CallLongMethodA (object, method, argValues);
271266 nativeInvokeResult = (void *) nativeLong;
272267 }
273268 else if (strcmp (returnType, " Z" ) == 0 ) {
274- auto nativeBool = gCurEnv ->CallBooleanMethodA (object, method, argValues);
269+ auto nativeBool = getEnv () ->CallBooleanMethodA (object, method, argValues);
275270 nativeInvokeResult = (void *) nativeBool;
276271 }
277272 else if (strcmp (returnType, " V" ) == 0 ) {
278- gCurEnv ->CallVoidMethodA (object, method, argValues);
273+ getEnv () ->CallVoidMethodA (object, method, argValues);
279274 }
280275
281276 free (argValues);
@@ -307,20 +302,18 @@ NativeMethodCallback getCallbackMethod(jlong targetAddr, char *functionName) {
307302}
308303
309304void registerNativeCallback (void *target, char * targetName, char *funName, void *callback) {
310- attachThread ();
311-
312- jclass callbackManager = findClass (gCurEnv , " com/dartnative/dart_native/CallbackManager" );
313- jmethodID registerCallback = gCurEnv ->GetStaticMethodID (callbackManager, " registerCallback" , " (JLjava/lang/String;)Ljava/lang/Object;" );
305+ jclass callbackManager = findClass (getEnv (), " com/dartnative/dart_native/CallbackManager" );
306+ jmethodID registerCallback = getEnv ()->GetStaticMethodID (callbackManager, " registerCallback" , " (JLjava/lang/String;)Ljava/lang/Object;" );
314307 jlong targetAddr = (jlong)target;
315308 jvalue *argValues = new jvalue[2 ];
316309 argValues[0 ].j = targetAddr;
317- argValues[1 ].l = gCurEnv ->NewStringUTF (targetName);
318- jobject callbackOJ = gCurEnv ->NewGlobalRef (gCurEnv ->CallStaticObjectMethodA (callbackManager, registerCallback, argValues));
310+ argValues[1 ].l = getEnv () ->NewStringUTF (targetName);
311+ jobject callbackOJ = getEnv () ->NewGlobalRef (getEnv () ->CallStaticObjectMethodA (callbackManager, registerCallback, argValues));
319312 callbackObjCache[target] = callbackOJ;
320313 targetCache[targetAddr] = target;
321314
322315 registerCallbackManager (targetAddr, funName, callback);
323- gCurEnv ->DeleteLocalRef (callbackManager);
316+ getEnv () ->DeleteLocalRef (callbackManager);
324317 free (argValues);
325318}
326319
0 commit comments