Skip to content

Commit 2d37fdb

Browse files
author
huizzzhou
committed
feat: optimization
1 parent 614ce8b commit 2d37fdb

File tree

3 files changed

+78
-83
lines changed

3 files changed

+78
-83
lines changed

dart_native/android/src/main/jni/dart_native.cpp

Lines changed: 68 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ extern "C" {
1616
static JavaVM *gJvm = nullptr;
1717
static jobject gClassLoader;
1818
static jmethodID gFindClassMethod;
19-
static JNIEnv *gCurEnv = nullptr;
2019
static pthread_key_t detachKey = 0;
2120

2221
typedef void (*NativeMethodCallback)(
@@ -36,45 +35,49 @@ static std::map<void *, jobject> callbackObjCache;
3635
static std::map<jlong, std::map<std::string, NativeMethodCallback>> callbackManagerCache;
3736
static 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

5139
void 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+
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;
6367
}
6468
}
6569

6670
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
6771
NSLog("JNI_OnLoad");
6872
gJvm = pjvm; // cache the JavaVM pointer
69-
gCurEnv = getEnv();
7073
//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",
7578
"()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",
7881
"(Ljava/lang/String;)Ljava/lang/Class;");
7982

8083
NSLog("JNI_OnLoad finish");
@@ -88,12 +91,11 @@ char *spliceChar(char *dest, char *src) {
8891
return result;
8992
}
9093

91-
char *generateSignature(char **argTypes) {
94+
char *generateSignature(char **argTypes, int argCount) {
9295
char *signature = const_cast<char *>("(");
93-
int argCount = 0;
9496
if (argTypes != nullptr)
9597
{
96-
for (; *argTypes; ++argTypes, ++argCount) {
98+
for (int i = 0; i < argCount; ++argTypes, i++) {
9799
char *templeSignature = spliceChar(signature, *argTypes);
98100
signature = templeSignature;
99101
free(templeSignature);
@@ -102,12 +104,12 @@ char *generateSignature(char **argTypes) {
102104
return spliceChar(signature, const_cast<char *>(")"));
103105
}
104106

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) {
107109
char *argType = *argTypes;
108110
if (strlen(argType) > 1) {
109111
if (strcmp(argType, "Ljava/lang/String;") == 0) {
110-
argValues[index].l = gCurEnv->NewStringUTF((char *)*args);
112+
argValues[index].l = getEnv()->NewStringUTF((char *)*args);
111113
}
112114
else {
113115
jobject object = callbackObjCache.count(*args) ? callbackObjCache[*args] : static_cast<jobject>(*args);
@@ -156,38 +158,34 @@ jclass findClass(JNIEnv *env, const char *name) {
156158
return nativeClass;
157159
}
158160

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);
164166
}
165167
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);
168170
free(argValues);
169171
free(constructorSig);
170172
return newObj;
171173
}
172174

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);
177177

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));
180180

181181
return newObj;
182182
}
183183

184184

185185
void releaseTargetClass(void *classPtr) {
186-
attachThread();
187-
188186
jobject object = static_cast<jobject>(classPtr);
189187
cache.erase(object);
190-
gCurEnv->DeleteGlobalRef(object);
188+
getEnv()->DeleteGlobalRef(object);
191189
}
192190

193191
void retain(void *classPtr) {
@@ -211,71 +209,70 @@ void release(void *classPtr) {
211209
referenceCount[object] = count - 1;
212210
}
213211

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) {
215213
void *nativeInvokeResult = nullptr;
216214

217-
attachThread();
218215
jobject object = static_cast<jobject>(classPtr);
219216
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);
224221
}
225222
char *methodSignature = spliceChar(signature, returnType);
226-
jmethodID method = gCurEnv->GetMethodID(cls, methodName, methodSignature);
223+
jmethodID method = getEnv()->GetMethodID(cls, methodName, methodSignature);
227224
NSLog("call method: %s descriptor: %s", methodName, methodSignature);
228225

229226
if (strlen(returnType) > 1) {
230227
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);
232229
jboolean isCopy = JNI_FALSE;
233-
nativeInvokeResult = (char *) gCurEnv->GetStringUTFChars(javaString, &isCopy);
230+
nativeInvokeResult = (char *) getEnv()->GetStringUTFChars(javaString, &isCopy);
234231
}
235232
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);
238235
//store class value
239-
cache[obj] = static_cast<jclass>(gCurEnv->NewGlobalRef(objCls));
236+
cache[obj] = static_cast<jclass>(getEnv()->NewGlobalRef(objCls));
240237
nativeInvokeResult = obj;
241238
}
242239
}
243240
else if (strcmp(returnType, "C") == 0) {
244-
auto nativeChar = gCurEnv->CallCharMethodA(object, method, argValues);
241+
auto nativeChar = getEnv()->CallCharMethodA(object, method, argValues);
245242
nativeInvokeResult = (void *) nativeChar;
246243
}
247244
else if(strcmp(returnType, "I") == 0) {
248-
auto nativeInt = gCurEnv->CallIntMethodA(object, method, argValues);
245+
auto nativeInt = getEnv()->CallIntMethodA(object, method, argValues);
249246
nativeInvokeResult = (void *) nativeInt;
250247
}
251248
else if(strcmp(returnType, "D") == 0) {
252-
auto nativeDouble = gCurEnv->CallDoubleMethodA(object, method, argValues);
249+
auto nativeDouble = getEnv()->CallDoubleMethodA(object, method, argValues);
253250
double cDouble = (double) nativeDouble;
254251
memcpy(&nativeInvokeResult, &cDouble, sizeof(double));
255252
}
256253
else if(strcmp(returnType, "F") == 0) {
257-
auto nativeDouble = gCurEnv->CallFloatMethodA(object, method, argValues);
254+
auto nativeDouble = getEnv()->CallFloatMethodA(object, method, argValues);
258255
float cDouble = (float) nativeDouble;
259256
memcpy(&nativeInvokeResult, &cDouble, sizeof(float));
260257
}
261258
else if(strcmp(returnType, "B") == 0) {
262-
auto nativeByte = gCurEnv->CallByteMethodA(object, method, argValues);
259+
auto nativeByte = getEnv()->CallByteMethodA(object, method, argValues);
263260
nativeInvokeResult = (void *) nativeByte;
264261
}
265262
else if(strcmp(returnType, "S") == 0) {
266-
auto nativeShort = gCurEnv->CallShortMethodA(object, method, argValues);
263+
auto nativeShort = getEnv()->CallShortMethodA(object, method, argValues);
267264
nativeInvokeResult = (void *) nativeShort;
268265
}
269266
else if(strcmp(returnType, "J") == 0) {
270-
auto nativeLong = gCurEnv->CallLongMethodA(object, method, argValues);
267+
auto nativeLong = getEnv()->CallLongMethodA(object, method, argValues);
271268
nativeInvokeResult = (void *) nativeLong;
272269
}
273270
else if(strcmp(returnType, "Z") == 0) {
274-
auto nativeBool = gCurEnv->CallBooleanMethodA(object, method, argValues);
271+
auto nativeBool = getEnv()->CallBooleanMethodA(object, method, argValues);
275272
nativeInvokeResult = (void *) nativeBool;
276273
}
277274
else if(strcmp(returnType, "V") == 0) {
278-
gCurEnv->CallVoidMethodA(object, method, argValues);
275+
getEnv()->CallVoidMethodA(object, method, argValues);
279276
}
280277

281278
free(argValues);
@@ -307,20 +304,18 @@ NativeMethodCallback getCallbackMethod(jlong targetAddr, char *functionName) {
307304
}
308305

309306
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;");
314309
jlong targetAddr = (jlong)target;
315310
jvalue *argValues = new jvalue[2];
316311
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));
319314
callbackObjCache[target] = callbackOJ;
320315
targetCache[targetAddr] = target;
321316

322317
registerCallbackManager(targetAddr, funName, callback);
323-
gCurEnv->DeleteLocalRef(callbackManager);
318+
getEnv()->DeleteLocalRef(callbackManager);
324319
free(argValues);
325320
}
326321

dart_native/lib/src/android/runtime/functions.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ typedef MethodNativeCallback = Void Function(
1616
/// input : className
1717
/// return : classObject
1818
final Pointer<Void> Function(Pointer<Utf8> clsName,
19-
Pointer<Pointer<Void>> argsPtrs, Pointer<Pointer<Utf8>> typePtrs)
19+
Pointer<Pointer<Void>> argsPtrs, Pointer<Pointer<Utf8>> typePtrs, int)
2020
nativeCreateClass = nativeDylib
2121
?.lookup<
2222
NativeFunction<
2323
Pointer<Void> Function(
2424
Pointer<Utf8> clsName,
2525
Pointer<Pointer<Void>> argsPtrs,
26-
Pointer<Pointer<Utf8>> typePtrs)>>("createTargetClass")
26+
Pointer<Pointer<Utf8>> typePtrs,
27+
Int32 argCount)>>("createTargetClass")
2728
?.asFunction();
2829

2930

@@ -38,7 +39,7 @@ nativeCreateClass = nativeDylib
3839
///
3940
/// @return: 返回值指针
4041
final Pointer<Void> Function(Pointer<Void> objectPtr, Pointer<Utf8> methodName,
41-
Pointer<Pointer<Void>> argsPtrs, Pointer<Pointer<Utf8>> typePtrs, Pointer<Utf8> returnType)
42+
Pointer<Pointer<Void>> argsPtrs, Pointer<Pointer<Utf8>> typePtrs, int, Pointer<Utf8> returnType)
4243
nativeInvokeNeo = nativeDylib
4344
?.lookup<
4445
NativeFunction<
@@ -47,6 +48,7 @@ nativeInvokeNeo = nativeDylib
4748
Pointer<Utf8> methodName,
4849
Pointer<Pointer<Void>> argsPtrs,
4950
Pointer<Pointer<Utf8>> typePtrs,
51+
Int32 argCount,
5052
Pointer<Utf8> returnType)>>("invokeNativeMethodNeo")
5153
?.asFunction();
5254

dart_native/lib/src/android/runtime/jobject.dart

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class JObject extends Class {
2828

2929
if (pointer == null) {
3030
Pointer<Utf8> classNamePtr = Utf8.toUtf8(super.className);
31-
pointer = nativeCreateClass(classNamePtr, nullptr, nullptr);
31+
pointer = nativeCreateClass(classNamePtr, nullptr, nullptr, 0);
3232
free(classNamePtr);
3333
}
3434

@@ -40,7 +40,7 @@ class JObject extends Class {
4040
ArgumentsPointers pointers = _parseArguments(args);
4141
Pointer<Utf8> classNamePtr = Utf8.toUtf8(super.className);
4242
_ptr = nativeCreateClass(
43-
classNamePtr, pointers.pointers, pointers.typePointers);
43+
classNamePtr, pointers.pointers, pointers.typePointers, args.length);
4444
free(classNamePtr);
4545
passJObjectToNative(this);
4646
pointers.freePointers();
@@ -57,7 +57,7 @@ class JObject extends Class {
5757

5858
ArgumentsPointers pointers = _parseArguments(args, argsSignature);
5959
Pointer<Void> invokeMethodRet = nativeInvokeNeo(_ptr, methodNamePtr,
60-
pointers.pointers, pointers.typePointers, returnTypePtr);
60+
pointers.pointers, pointers.typePointers, args.length, returnTypePtr);
6161

6262
dynamic result = loadValueFromPointer(invokeMethodRet, returnType);
6363
pointers.freePointers();
@@ -78,8 +78,8 @@ class JObject extends Class {
7878
Pointer<Pointer<Void>> pointers = nullptr;
7979
Pointer<Pointer<Utf8>> typePointers = nullptr;
8080
if (args != null) {
81-
pointers = allocate<Pointer<Void>>(count: args.length + 1);
82-
typePointers = allocate<Pointer<Utf8>>(count: args.length + 1);
81+
pointers = allocate<Pointer<Void>>(count: args.length);
82+
typePointers = allocate<Pointer<Utf8>>(count: args.length);
8383
for (var i = 0; i < args.length; i++) {
8484
var arg = args[i];
8585
if (arg == null) {
@@ -92,8 +92,6 @@ class JObject extends Class {
9292
storeValueToPointer(arg, pointers.elementAt(i),
9393
typePointers.elementAt(i), argSignature);
9494
}
95-
pointers.elementAt(args.length).value = nullptr;
96-
typePointers.elementAt(args.length).value = nullptr;
9795
}
9896
return ArgumentsPointers(pointers, typePointers);
9997
}

0 commit comments

Comments
 (0)