@@ -16,7 +16,6 @@ extern "C" {
16
16
static JavaVM *gJvm = nullptr ;
17
17
static jobject gClassLoader ;
18
18
static jmethodID gFindClassMethod ;
19
- static JNIEnv *gCurEnv = nullptr ;
20
19
static pthread_key_t detachKey = 0 ;
21
20
22
21
typedef void (*NativeMethodCallback)(
@@ -36,45 +35,48 @@ static std::map<void *, jobject> callbackObjCache;
36
35
static std::map<jlong, std::map<std::string, NativeMethodCallback>> callbackManagerCache;
37
36
static std::map<jlong, void *> targetCache;
38
37
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
- }
50
38
51
39
void detachThreadDestructor (void * arg) {
52
40
NSLog (" detach from current thread" );
53
41
gJvm ->DetachCurrentThread ();
54
42
detachKey = 0 ;
55
43
}
56
44
57
- void attachThread () {
45
+ JNIEnv *getEnv () {
46
+ if (gJvm == nullptr ) {
47
+ return nullptr ;
48
+ }
49
+
58
50
if (detachKey == 0 ) {
59
- NSLog (" attach to current thread" );
60
51
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 ;
63
66
}
64
67
}
65
68
66
69
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *pjvm, void *reserved) {
67
70
NSLog (" JNI_OnLoad" );
68
71
gJvm = pjvm; // cache the JavaVM pointer
69
- gCurEnv = getEnv ();
70
72
// 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" ,
75
77
" ()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" ,
78
80
" (Ljava/lang/String;)Ljava/lang/Class;" );
79
81
80
82
NSLog (" JNI_OnLoad finish" );
@@ -88,12 +90,11 @@ char *spliceChar(char *dest, char *src) {
88
90
return result;
89
91
}
90
92
91
- char *generateSignature (char **argTypes) {
93
+ char *generateSignature (char **argTypes, int argCount ) {
92
94
char *signature = const_cast <char *>(" (" );
93
- int argCount = 0 ;
94
95
if (argTypes != nullptr )
95
96
{
96
- for (; *argTypes ; ++argTypes, ++argCount ) {
97
+ for (int i = 0 ; i < argCount ; ++argTypes, i++ ) {
97
98
char *templeSignature = spliceChar (signature, *argTypes);
98
99
signature = templeSignature;
99
100
free (templeSignature);
@@ -102,12 +103,12 @@ char *generateSignature(char **argTypes) {
102
103
return spliceChar (signature, const_cast <char *>(" )" ));
103
104
}
104
105
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) {
107
108
char *argType = *argTypes;
108
109
if (strlen (argType) > 1 ) {
109
110
if (strcmp (argType, " Ljava/lang/String;" ) == 0 ) {
110
- argValues[index].l = gCurEnv ->NewStringUTF ((char *)*args);
111
+ argValues[index].l = getEnv () ->NewStringUTF ((char *)*args);
111
112
}
112
113
else {
113
114
jobject object = callbackObjCache.count (*args) ? callbackObjCache[*args] : static_cast <jobject>(*args);
@@ -156,38 +157,34 @@ jclass findClass(JNIEnv *env, const char *name) {
156
157
return nativeClass;
157
158
}
158
159
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 );
164
165
}
165
166
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);
168
169
free (argValues);
169
170
free (constructorSig);
170
171
return newObj;
171
172
}
172
173
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);
177
176
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));
180
179
181
180
return newObj;
182
181
}
183
182
184
183
185
184
void releaseTargetClass (void *classPtr) {
186
- attachThread ();
187
-
188
185
jobject object = static_cast <jobject>(classPtr);
189
186
cache.erase (object);
190
- gCurEnv ->DeleteGlobalRef (object);
187
+ getEnv () ->DeleteGlobalRef (object);
191
188
}
192
189
193
190
void retain (void *classPtr) {
@@ -211,71 +208,69 @@ void release(void *classPtr) {
211
208
referenceCount[object] = count - 1 ;
212
209
}
213
210
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) {
215
212
void *nativeInvokeResult = nullptr ;
216
213
217
- attachThread ();
218
214
jobject object = static_cast <jobject>(classPtr);
219
215
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 );
224
220
}
225
221
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);
228
223
229
224
if (strlen (returnType) > 1 ) {
230
225
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);
232
227
jboolean isCopy = JNI_FALSE;
233
- nativeInvokeResult = (char *) gCurEnv ->GetStringUTFChars (javaString, &isCopy);
228
+ nativeInvokeResult = (char *) getEnv () ->GetStringUTFChars (javaString, &isCopy);
234
229
}
235
230
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);
238
233
// store class value
239
- cache[obj] = static_cast <jclass>(gCurEnv ->NewGlobalRef (objCls));
234
+ cache[obj] = static_cast <jclass>(getEnv () ->NewGlobalRef (objCls));
240
235
nativeInvokeResult = obj;
241
236
}
242
237
}
243
238
else if (strcmp (returnType, " C" ) == 0 ) {
244
- auto nativeChar = gCurEnv ->CallCharMethodA (object, method, argValues);
239
+ auto nativeChar = getEnv () ->CallCharMethodA (object, method, argValues);
245
240
nativeInvokeResult = (void *) nativeChar;
246
241
}
247
242
else if (strcmp (returnType, " I" ) == 0 ) {
248
- auto nativeInt = gCurEnv ->CallIntMethodA (object, method, argValues);
243
+ auto nativeInt = getEnv () ->CallIntMethodA (object, method, argValues);
249
244
nativeInvokeResult = (void *) nativeInt;
250
245
}
251
246
else if (strcmp (returnType, " D" ) == 0 ) {
252
- auto nativeDouble = gCurEnv ->CallDoubleMethodA (object, method, argValues);
247
+ auto nativeDouble = getEnv () ->CallDoubleMethodA (object, method, argValues);
253
248
double cDouble = (double ) nativeDouble;
254
249
memcpy (&nativeInvokeResult, &cDouble, sizeof (double ));
255
250
}
256
251
else if (strcmp (returnType, " F" ) == 0 ) {
257
- auto nativeDouble = gCurEnv ->CallFloatMethodA (object, method, argValues);
252
+ auto nativeDouble = getEnv () ->CallFloatMethodA (object, method, argValues);
258
253
float cDouble = (float ) nativeDouble;
259
254
memcpy (&nativeInvokeResult, &cDouble, sizeof (float ));
260
255
}
261
256
else if (strcmp (returnType, " B" ) == 0 ) {
262
- auto nativeByte = gCurEnv ->CallByteMethodA (object, method, argValues);
257
+ auto nativeByte = getEnv () ->CallByteMethodA (object, method, argValues);
263
258
nativeInvokeResult = (void *) nativeByte;
264
259
}
265
260
else if (strcmp (returnType, " S" ) == 0 ) {
266
- auto nativeShort = gCurEnv ->CallShortMethodA (object, method, argValues);
261
+ auto nativeShort = getEnv () ->CallShortMethodA (object, method, argValues);
267
262
nativeInvokeResult = (void *) nativeShort;
268
263
}
269
264
else if (strcmp (returnType, " J" ) == 0 ) {
270
- auto nativeLong = gCurEnv ->CallLongMethodA (object, method, argValues);
265
+ auto nativeLong = getEnv () ->CallLongMethodA (object, method, argValues);
271
266
nativeInvokeResult = (void *) nativeLong;
272
267
}
273
268
else if (strcmp (returnType, " Z" ) == 0 ) {
274
- auto nativeBool = gCurEnv ->CallBooleanMethodA (object, method, argValues);
269
+ auto nativeBool = getEnv () ->CallBooleanMethodA (object, method, argValues);
275
270
nativeInvokeResult = (void *) nativeBool;
276
271
}
277
272
else if (strcmp (returnType, " V" ) == 0 ) {
278
- gCurEnv ->CallVoidMethodA (object, method, argValues);
273
+ getEnv () ->CallVoidMethodA (object, method, argValues);
279
274
}
280
275
281
276
free (argValues);
@@ -307,20 +302,18 @@ NativeMethodCallback getCallbackMethod(jlong targetAddr, char *functionName) {
307
302
}
308
303
309
304
void 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;" );
314
307
jlong targetAddr = (jlong)target;
315
308
jvalue *argValues = new jvalue[2 ];
316
309
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));
319
312
callbackObjCache[target] = callbackOJ;
320
313
targetCache[targetAddr] = target;
321
314
322
315
registerCallbackManager (targetAddr, funName, callback);
323
- gCurEnv ->DeleteLocalRef (callbackManager);
316
+ getEnv () ->DeleteLocalRef (callbackManager);
324
317
free (argValues);
325
318
}
326
319
0 commit comments