Skip to content

Commit

Permalink
fix(Android): 修复Callback形式返回的视图内存回收问题
Browse files Browse the repository at this point in the history
  • Loading branch information
bbssyyuui committed Mar 31, 2023
1 parent c3440b7 commit c19d071
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public static NAPICallback wrapper(long context, long value) {

private NAPICallback(long context, long value) {
super(context, value);
protect();
}

@MainThread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public class NAPIValue implements JSValue {

public long context;
public long value;
private volatile boolean isUnprotected = true;

public static NAPIValue wrapper(long context, long value) {
return new NAPIValue(context, value);
Expand Down Expand Up @@ -242,20 +241,14 @@ public boolean isNull() {
@Override
public void protect() {
UIThreadUtil.assetOnMainThreadCall("NAPIValue.protect");
if (isUnprotected) {
isUnprotected = false;
JSEngine.protect(context, value);
}
JSEngine.protect(context, value);
}

@MainThread
@Override
public void unprotect() {
UIThreadUtil.assetOnMainThreadCall("NAPIValue.unprotect");
if (!isUnprotected) {
isUnprotected = true;
JSEngine.unprotect(context, value);
}
JSEngine.unprotect(context, value);
}

@Override
Expand Down Expand Up @@ -287,7 +280,6 @@ public String toString() {
return "NAPIValue{" +
"context=" + context +
", value=" + value +
", isUnprotected=" + isUnprotected +
'}';
}
}
52 changes: 15 additions & 37 deletions android/hummer-core/src/main/jni/napi/hummer/JSEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ static NAPIValue invoke(NAPIEnv globalEnv, NAPICallbackInfo info) {
env->DeleteLocalRef(params);
JNI_DetachEnv();

NAPIHandleScope handleScope;
napi_open_handle_scope(globalEnv, &handleScope);
// NAPIHandleScope handleScope;
// napi_open_handle_scope(globalEnv, &handleScope);

NAPIValue r = JSUtils::JavaObjectToJsValue(globalEnv, ret);

napi_close_handle_scope(globalEnv, handleScope);
// napi_close_handle_scope(globalEnv, handleScope);

return r;
}
Expand Down Expand Up @@ -113,7 +113,7 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_evaluateJavaScript(JNIEnv *en
return obj;
}

return JSUtils::JsValueToJavaObject(globalEnv, result);
return JSUtils::JsValueToJavaObject(globalEnv, result, true);
}

extern "C"
Expand Down Expand Up @@ -168,7 +168,7 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_evaluateBytecode(JNIEnv *env,
return obj;
}

return JSUtils::JsValueToJavaObject(globalEnv, result);
return JSUtils::JsValueToJavaObject(globalEnv, result, true);
}

extern "C"
Expand Down Expand Up @@ -219,7 +219,7 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_getProperty(JNIEnv *env, jcla
}

env->ReleaseStringUTFChars(key, cKey);
jobject r = JSUtils::JsValueToJavaObject(globalEnv, ret);
jobject r = JSUtils::JsValueToJavaObject(globalEnv, ret, true);

napi_close_handle_scope(globalEnv, handleScope);
return r;
Expand Down Expand Up @@ -314,7 +314,7 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_callFunction(JNIEnv *env, jcl
return nullptr;
}

jobject r = JSUtils::JsValueToJavaObject(globalEnv, result);
jobject r = JSUtils::JsValueToJavaObject(globalEnv, result, true);
napi_close_handle_scope(globalEnv, handleScope);
return r;
}
Expand All @@ -333,20 +333,8 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_isJSValueValid(JNIEnv *env, j
if (globalEnv == nullptr) {
return false;
}

NAPIHandleScope handleScope;
napi_open_handle_scope(globalEnv, &handleScope);

auto value = JSUtils::toJsValue(globalEnv, js_value);
NAPIValueType type;
auto status = napi_typeof(globalEnv, value, &type);

napi_close_handle_scope(globalEnv, handleScope);

if (status != NAPICommonOK) {
return false;
}
return type != NAPIUndefined && type != NAPINull;
auto valueRef = JSUtils::toJsValueRef(js_value);
return JSUtils::isJSValueValid(globalEnv, valueRef);
}

extern "C"
Expand All @@ -356,28 +344,18 @@ Java_com_didi_hummer_core_engine_napi_jni_JSEngine_isJSValueEqual(JNIEnv *env, j
if (globalEnv == nullptr) {
return false;
}

NAPIHandleScope handleScope;
napi_open_handle_scope(globalEnv, &handleScope);

auto valueLeft = JSUtils::toJsValue(globalEnv, js_value_l);
auto valueRight = JSUtils::toJsValue(globalEnv, js_value_r);

bool ret;
auto status = napi_strict_equals(globalEnv, valueLeft, valueRight, &ret);

napi_close_handle_scope(globalEnv, handleScope);

if (status != NAPIExceptionOK) {
return false;
}
return ret;
auto valueRefLeft = JSUtils::toJsValueRef(js_value_l);
auto valueRefRight = JSUtils::toJsValueRef(js_value_r);
return JSUtils::isJSValueEqual(globalEnv, valueRefLeft, valueRefRight);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_didi_hummer_core_engine_napi_jni_JSEngine_protect(JNIEnv *env, jclass clazz, jlong js_context, jlong js_value) {
auto globalEnv = JSUtils::toJsContext(js_context);
if (globalEnv == nullptr) {
return;
}
auto valueRef = JSUtils::toJsValueRef(js_value);
napi_reference_ref(globalEnv, valueRef, nullptr);
}
Expand Down
59 changes: 54 additions & 5 deletions android/hummer-core/src/main/jni/napi/hummer/JSUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ int64_t JSUtils::toJsValuePtr(NAPIRef valueRef) {
}

int64_t JSUtils::toJsValuePtr(NAPIEnv env, NAPIValue value) {
return toJsValuePtr(createJsValueRef(env, value));
return JSUtils::toJsValuePtr(env, value, false);
}

int64_t JSUtils::toJsValuePtr(NAPIEnv env, NAPIValue value, bool isStrongRef) {
return toJsValuePtr(createJsValueRef(env, value, isStrongRef));
}

NAPIValue JSUtils::toJsValue(NAPIEnv env, int64_t valuePtr) {
Expand All @@ -146,13 +150,13 @@ NAPIValue JSUtils::getJsValueFromRef(NAPIEnv env, NAPIRef valueRef) {
return value;
}

NAPIRef JSUtils::createJsValueRef(NAPIEnv env, NAPIValue value) {
NAPIRef JSUtils::createJsValueRef(NAPIEnv env, NAPIValue value, bool isStrongRef) {
if (value == nullptr) {
return nullptr;
}

NAPIRef valueRef;
auto status = napi_create_reference(env, value, 0, &valueRef);
auto status = napi_create_reference(env, value, isStrongRef ? 1 : 0, &valueRef);
if (status != NAPIExceptionOK) {
return nullptr;
}
Expand Down Expand Up @@ -213,6 +217,10 @@ NAPIValue JSUtils::createJsUndefined(NAPIEnv env) {
}

jobject JSUtils::JsValueToJavaObject(NAPIEnv globalEnv, NAPIValue value) {
return JSUtils::JsValueToJavaObject(globalEnv, value, false);
}

jobject JSUtils::JsValueToJavaObject(NAPIEnv globalEnv, NAPIValue value, bool isStrongRef) {
JNIEnv* env = JNI_GetEnv();
NAPIValueType type;
auto status = napi_typeof(globalEnv, value, &type);
Expand All @@ -234,11 +242,11 @@ jobject JSUtils::JsValueToJavaObject(NAPIEnv globalEnv, NAPIValue value) {
obj = JSUtils::toJavaString(globalEnv, value);
} else if (type == NAPIFunction) {
jlong ctxPtr = JSUtils::toJsContextPtr(globalEnv);
jlong valuePtr = JSUtils::toJsValuePtr(globalEnv, value);
jlong valuePtr = JSUtils::toJsValuePtr(globalEnv, value, true);
obj = env->CallStaticObjectMethod(jsCallbackCls, jsCallbackInitMethodID, ctxPtr, valuePtr);
} else {
jlong ctxPtr = JSUtils::toJsContextPtr(globalEnv);
jlong valuePtr = JSUtils::toJsValuePtr(globalEnv, value);
jlong valuePtr = JSUtils::toJsValuePtr(globalEnv, value, isStrongRef);
obj = env->CallStaticObjectMethod(jsValueCls, jsValueInitMethodID, ctxPtr, valuePtr);
}

Expand Down Expand Up @@ -276,6 +284,47 @@ NAPIValue JSUtils::JavaObjectToJsValue(NAPIEnv globalEnv, jobject value) {
return val;
}

bool JSUtils::isJSValueValid(NAPIEnv env, NAPIValue value) {
NAPIValueType type;
auto status = napi_typeof(env, value, &type);
if (status != NAPICommonOK) {
return false;
}
return type != NAPIUndefined && type != NAPINull;
}

bool JSUtils::isJSValueValid(NAPIEnv env, NAPIRef valueRef) {
NAPIHandleScope handleScope;
napi_open_handle_scope(env, &handleScope);

auto ret = isJSValueValid(env, getJsValueFromRef(env, valueRef));

napi_close_handle_scope(env, handleScope);
return ret;
}

bool JSUtils::isJSValueEqual(NAPIEnv env, NAPIValue valueLeft, NAPIValue valueRight) {
bool ret;
auto status = napi_strict_equals(env, valueLeft, valueRight, &ret);

if (status != NAPIExceptionOK) {
return false;
}
return ret;
}

bool JSUtils::isJSValueEqual(NAPIEnv env, NAPIRef valueRefLeft, NAPIRef valueRefRight) {
NAPIHandleScope handleScope;
napi_open_handle_scope(env, &handleScope);

auto valueLeft = getJsValueFromRef(env, valueRefLeft);
auto valueRight = getJsValueFromRef(env, valueRefRight);
bool ret = isJSValueEqual(env, valueLeft, valueRight);

napi_close_handle_scope(env, handleScope);
return ret;
}

void JSUtils::printDumpReferenceTables(JNIEnv *env) {
jclass vm_class = (*env).FindClass("dalvik/system/VMDebug");
jmethodID dump_mid = env->GetStaticMethodID(vm_class, "dumpReferenceTables", "()V");
Expand Down
9 changes: 8 additions & 1 deletion android/hummer-core/src/main/jni/napi/hummer/JSUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ class JSUtils {
static NAPIRef toJsValueRef(int64_t valuePtr);
static int64_t toJsValuePtr(NAPIRef valueRef);
static int64_t toJsValuePtr(NAPIEnv env, NAPIValue value);
static int64_t toJsValuePtr(NAPIEnv env, NAPIValue value, bool isStrongRef);
static NAPIValue toJsValue(NAPIEnv env, int64_t valuePtr);
static NAPIValue getJsValueFromRef(NAPIEnv env, NAPIRef valueRef);
static NAPIRef createJsValueRef(NAPIEnv env, NAPIValue value);
static NAPIRef createJsValueRef(NAPIEnv env, NAPIValue value, bool isStrongRef);

static const char *toCString(NAPIEnv env, NAPIValue value);
static void freeCString(NAPIEnv env, const char *cString);
Expand All @@ -62,8 +63,14 @@ class JSUtils {
static NAPIValue createJsUndefined(NAPIEnv env);

static jobject JsValueToJavaObject(NAPIEnv env, NAPIValue value);
static jobject JsValueToJavaObject(NAPIEnv env, NAPIValue value, bool isStrongRef);
static NAPIValue JavaObjectToJsValue(NAPIEnv globalEnv, jobject value);

static bool isJSValueValid(NAPIEnv env, NAPIValue value);
static bool isJSValueValid(NAPIEnv env, NAPIRef valueRef);
static bool isJSValueEqual(NAPIEnv env, NAPIValue valueLeft, NAPIValue valueRight);
static bool isJSValueEqual(NAPIEnv env, NAPIRef valueRefLeft, NAPIRef valueRight);

static void printDumpReferenceTables(JNIEnv *env);

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ public void onCreate() {}
@Override
public void onDestroy() {
isDestroyed.set(true);
jsValue.unprotect();
}

public void setUrl(String api) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@Component("Timer")
public class Timer implements ILifeCycle {

private static Handler timerHandler = new Handler(Looper.getMainLooper());
private Handler timerHandler = new Handler(Looper.getMainLooper());

private JSValue jsValue;
private Runnable intervalRunnable;
Expand All @@ -43,8 +43,12 @@ public void onCreate() {
@Override
public void onDestroy() {
isDestroyed.set(true);
clearInterval();
clearTimeout();
if (intervalRunnable != null) {
timerHandler.removeCallbacks(intervalRunnable);
}
if (timeoutRunnable != null) {
timerHandler.removeCallbacks(timeoutRunnable);
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions examples/hummer/unit-test/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"type": "hummerdirect",
"workspaceRoot": "${workspaceFolder}",
"request": "attach",
"port": 8000
}]
}
2 changes: 1 addition & 1 deletion examples/hummer/unit-test/src/Comp_Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class RootView extends View {

let infoText = new Text();

subLayout1.appendChild(input);
subLayout1.appendChild(this.feeInput);
subLayout1.appendChild(btn1);
subLayout2.appendChild(textArea);
subLayout2.appendChild(btn2);
Expand Down
Loading

0 comments on commit c19d071

Please sign in to comment.