@@ -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,49 @@ 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
+ NSLog (" JNI_OK" );
59
+ return env;
60
+ case JNI_EDETACHED:
61
+ NSLog (" attach to current thread" );
62
+ gJvm ->AttachCurrentThread (&env, NULL );
63
+ return env;
64
+ default :
65
+ NSLog (" fail to get env" );
66
+ return nullptr ;
63
67
}
64
68
}
65
69
66
70
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *pjvm, void *reserved) {
67
71
NSLog (" JNI_OnLoad" );
68
72
gJvm = pjvm; // cache the JavaVM pointer
69
- gCurEnv = getEnv ();
70
73
// 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" ,
74
+ auto randomClass = getEnv () ->FindClass (" com/dartnative/dart_native/DartNativePlugin" );
75
+ jclass classClass = getEnv () ->GetObjectClass (randomClass);
76
+ auto classLoaderClass = getEnv () ->FindClass (" java/lang/ClassLoader" );
77
+ auto getClassLoaderMethod = getEnv () ->GetMethodID (classClass, " getClassLoader" ,
75
78
" ()Ljava/lang/ClassLoader;" );
76
- gClassLoader = gCurEnv ->NewGlobalRef (gCurEnv ->CallObjectMethod (randomClass, getClassLoaderMethod));
77
- gFindClassMethod = gCurEnv ->GetMethodID (classLoaderClass, " findClass" ,
79
+ gClassLoader = getEnv () ->NewGlobalRef (getEnv () ->CallObjectMethod (randomClass, getClassLoaderMethod));
80
+ gFindClassMethod = getEnv () ->GetMethodID (classLoaderClass, " findClass" ,
78
81
" (Ljava/lang/String;)Ljava/lang/Class;" );
79
82
80
83
NSLog (" JNI_OnLoad finish" );
@@ -88,12 +91,11 @@ char *spliceChar(char *dest, char *src) {
88
91
return result;
89
92
}
90
93
91
- char *generateSignature (char **argTypes) {
94
+ char *generateSignature (char **argTypes, int argCount ) {
92
95
char *signature = const_cast <char *>(" (" );
93
- int argCount = 0 ;
94
96
if (argTypes != nullptr )
95
97
{
96
- for (; *argTypes ; ++argTypes, ++argCount ) {
98
+ for (int i = 0 ; i < argCount ; ++argTypes, i++ ) {
97
99
char *templeSignature = spliceChar (signature, *argTypes);
98
100
signature = templeSignature;
99
101
free (templeSignature);
@@ -102,12 +104,12 @@ char *generateSignature(char **argTypes) {
102
104
return spliceChar (signature, const_cast <char *>(" )" ));
103
105
}
104
106
105
- void fillArgs (void **args, char **argTypes, jvalue *argValues) {
106
- for (jsize index (0 ); *argTypes ; ++args, ++index, ++argTypes) {
107
+ void fillArgs (void **args, char **argTypes, jvalue *argValues, int argCount ) {
108
+ for (jsize index (0 ); index < argCount ; ++args, ++index, ++argTypes) {
107
109
char *argType = *argTypes;
108
110
if (strlen (argType) > 1 ) {
109
111
if (strcmp (argType, " Ljava/lang/String;" ) == 0 ) {
110
- argValues[index].l = gCurEnv ->NewStringUTF ((char *)*args);
112
+ argValues[index].l = getEnv () ->NewStringUTF ((char *)*args);
111
113
}
112
114
else {
113
115
jobject object = callbackObjCache.count (*args) ? callbackObjCache[*args] : static_cast <jobject>(*args);
@@ -156,38 +158,34 @@ jclass findClass(JNIEnv *env, const char *name) {
156
158
return nativeClass;
157
159
}
158
160
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);
161
+ jobject newObject (jclass cls, void **args, char **argTypes, int argCount ) {
162
+ char *signature = generateSignature (argTypes, argCount );
163
+ jvalue *argValues = new jvalue[argCount ];
164
+ if (argCount > 0 ) {
165
+ fillArgs (args, argTypes, argValues, argCount );
164
166
}
165
167
char *constructorSig = spliceChar (signature, const_cast <char *>(" V" ));
166
- jmethodID constructor = gCurEnv ->GetMethodID (cls, " <init>" , constructorSig);
167
- jobject newObj = gCurEnv ->NewObjectA (cls, constructor, argValues);
168
+ jmethodID constructor = getEnv () ->GetMethodID (cls, " <init>" , constructorSig);
169
+ jobject newObj = getEnv () ->NewObjectA (cls, constructor, argValues);
168
170
free (argValues);
169
171
free (constructorSig);
170
172
return newObj;
171
173
}
172
174
173
- void *createTargetClass (char *targetClassName, void **args, char **argTypes) {
174
- attachThread ();
175
-
176
- jclass cls = findClass (gCurEnv , targetClassName);
175
+ void *createTargetClass (char *targetClassName, void **args, char **argTypes, int argCount) {
176
+ jclass cls = findClass (getEnv (), targetClassName);
177
177
178
- jobject newObj = gCurEnv ->NewGlobalRef (newObject (cls, args, argTypes));
179
- cache[newObj] = static_cast <jclass>(gCurEnv ->NewGlobalRef (cls));
178
+ jobject newObj = getEnv () ->NewGlobalRef (newObject (cls, args, argTypes, argCount ));
179
+ cache[newObj] = static_cast <jclass>(getEnv () ->NewGlobalRef (cls));
180
180
181
181
return newObj;
182
182
}
183
183
184
184
185
185
void releaseTargetClass (void *classPtr) {
186
- attachThread ();
187
-
188
186
jobject object = static_cast <jobject>(classPtr);
189
187
cache.erase (object);
190
- gCurEnv ->DeleteGlobalRef (object);
188
+ getEnv () ->DeleteGlobalRef (object);
191
189
}
192
190
193
191
void retain (void *classPtr) {
@@ -211,71 +209,70 @@ void release(void *classPtr) {
211
209
referenceCount[object] = count - 1 ;
212
210
}
213
211
214
- void *invokeNativeMethodNeo (void *classPtr, char *methodName, void **args, char **argTypes, char *returnType) {
212
+ void *invokeNativeMethodNeo (void *classPtr, char *methodName, void **args, char **argTypes, int argCount, char *returnType) {
215
213
void *nativeInvokeResult = nullptr ;
216
214
217
- attachThread ();
218
215
jobject object = static_cast <jobject>(classPtr);
219
216
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);
217
+ char *signature = generateSignature (argTypes, argCount );
218
+ jvalue *argValues = new jvalue[argCount ];
219
+ if (argCount > 0 ) {
220
+ fillArgs (args, argTypes, argValues, argCount );
224
221
}
225
222
char *methodSignature = spliceChar (signature, returnType);
226
- jmethodID method = gCurEnv ->GetMethodID (cls, methodName, methodSignature);
223
+ jmethodID method = getEnv () ->GetMethodID (cls, methodName, methodSignature);
227
224
NSLog (" call method: %s descriptor: %s" , methodName, methodSignature);
228
225
229
226
if (strlen (returnType) > 1 ) {
230
227
if (strcmp (returnType, " Ljava/lang/String;" ) == 0 ) {
231
- jstring javaString = (jstring)gCurEnv ->CallObjectMethodA (object, method, argValues);
228
+ jstring javaString = (jstring) getEnv () ->CallObjectMethodA (object, method, argValues);
232
229
jboolean isCopy = JNI_FALSE;
233
- nativeInvokeResult = (char *) gCurEnv ->GetStringUTFChars (javaString, &isCopy);
230
+ nativeInvokeResult = (char *) getEnv () ->GetStringUTFChars (javaString, &isCopy);
234
231
}
235
232
else {
236
- jobject obj = gCurEnv ->NewGlobalRef (gCurEnv ->CallObjectMethodA (object, method, argValues));
237
- jclass objCls = gCurEnv ->GetObjectClass (obj);
233
+ jobject obj = getEnv () ->NewGlobalRef (getEnv () ->CallObjectMethodA (object, method, argValues));
234
+ jclass objCls = getEnv () ->GetObjectClass (obj);
238
235
// store class value
239
- cache[obj] = static_cast <jclass>(gCurEnv ->NewGlobalRef (objCls));
236
+ cache[obj] = static_cast <jclass>(getEnv () ->NewGlobalRef (objCls));
240
237
nativeInvokeResult = obj;
241
238
}
242
239
}
243
240
else if (strcmp (returnType, " C" ) == 0 ) {
244
- auto nativeChar = gCurEnv ->CallCharMethodA (object, method, argValues);
241
+ auto nativeChar = getEnv () ->CallCharMethodA (object, method, argValues);
245
242
nativeInvokeResult = (void *) nativeChar;
246
243
}
247
244
else if (strcmp (returnType, " I" ) == 0 ) {
248
- auto nativeInt = gCurEnv ->CallIntMethodA (object, method, argValues);
245
+ auto nativeInt = getEnv () ->CallIntMethodA (object, method, argValues);
249
246
nativeInvokeResult = (void *) nativeInt;
250
247
}
251
248
else if (strcmp (returnType, " D" ) == 0 ) {
252
- auto nativeDouble = gCurEnv ->CallDoubleMethodA (object, method, argValues);
249
+ auto nativeDouble = getEnv () ->CallDoubleMethodA (object, method, argValues);
253
250
double cDouble = (double ) nativeDouble;
254
251
memcpy (&nativeInvokeResult, &cDouble, sizeof (double ));
255
252
}
256
253
else if (strcmp (returnType, " F" ) == 0 ) {
257
- auto nativeDouble = gCurEnv ->CallFloatMethodA (object, method, argValues);
254
+ auto nativeDouble = getEnv () ->CallFloatMethodA (object, method, argValues);
258
255
float cDouble = (float ) nativeDouble;
259
256
memcpy (&nativeInvokeResult, &cDouble, sizeof (float ));
260
257
}
261
258
else if (strcmp (returnType, " B" ) == 0 ) {
262
- auto nativeByte = gCurEnv ->CallByteMethodA (object, method, argValues);
259
+ auto nativeByte = getEnv () ->CallByteMethodA (object, method, argValues);
263
260
nativeInvokeResult = (void *) nativeByte;
264
261
}
265
262
else if (strcmp (returnType, " S" ) == 0 ) {
266
- auto nativeShort = gCurEnv ->CallShortMethodA (object, method, argValues);
263
+ auto nativeShort = getEnv () ->CallShortMethodA (object, method, argValues);
267
264
nativeInvokeResult = (void *) nativeShort;
268
265
}
269
266
else if (strcmp (returnType, " J" ) == 0 ) {
270
- auto nativeLong = gCurEnv ->CallLongMethodA (object, method, argValues);
267
+ auto nativeLong = getEnv () ->CallLongMethodA (object, method, argValues);
271
268
nativeInvokeResult = (void *) nativeLong;
272
269
}
273
270
else if (strcmp (returnType, " Z" ) == 0 ) {
274
- auto nativeBool = gCurEnv ->CallBooleanMethodA (object, method, argValues);
271
+ auto nativeBool = getEnv () ->CallBooleanMethodA (object, method, argValues);
275
272
nativeInvokeResult = (void *) nativeBool;
276
273
}
277
274
else if (strcmp (returnType, " V" ) == 0 ) {
278
- gCurEnv ->CallVoidMethodA (object, method, argValues);
275
+ getEnv () ->CallVoidMethodA (object, method, argValues);
279
276
}
280
277
281
278
free (argValues);
@@ -307,20 +304,18 @@ NativeMethodCallback getCallbackMethod(jlong targetAddr, char *functionName) {
307
304
}
308
305
309
306
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;" );
307
+ jclass callbackManager = findClass (getEnv (), " com/dartnative/dart_native/CallbackManager" );
308
+ jmethodID registerCallback = getEnv ()->GetStaticMethodID (callbackManager, " registerCallback" , " (JLjava/lang/String;)Ljava/lang/Object;" );
314
309
jlong targetAddr = (jlong)target;
315
310
jvalue *argValues = new jvalue[2 ];
316
311
argValues[0 ].j = targetAddr;
317
- argValues[1 ].l = gCurEnv ->NewStringUTF (targetName);
318
- jobject callbackOJ = gCurEnv ->NewGlobalRef (gCurEnv ->CallStaticObjectMethodA (callbackManager, registerCallback, argValues));
312
+ argValues[1 ].l = getEnv () ->NewStringUTF (targetName);
313
+ jobject callbackOJ = getEnv () ->NewGlobalRef (getEnv () ->CallStaticObjectMethodA (callbackManager, registerCallback, argValues));
319
314
callbackObjCache[target] = callbackOJ;
320
315
targetCache[targetAddr] = target;
321
316
322
317
registerCallbackManager (targetAddr, funName, callback);
323
- gCurEnv ->DeleteLocalRef (callbackManager);
318
+ getEnv () ->DeleteLocalRef (callbackManager);
324
319
free (argValues);
325
320
}
326
321
0 commit comments