[WEEX-454][Android] fix can't find libweexjss when deploy fix can't find libweexjss when deploy
Bug: WEEX-454 Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/1e715624 Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/1e715624 Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/1e715624 Branch: refs/heads/release Commit: 1e715624b0b0b152e5de726a0ee20cddf3bb7661 Parents: ad255b3 Author: Darin <[email protected]> Authored: Tue Jun 12 17:21:53 2018 +0800 Committer: Darin <[email protected]> Committed: Tue Jun 12 17:21:53 2018 +0800 ---------------------------------------------------------------------- .../java/com/taobao/weex/WXEnvironment.java | 71 ++++++++++++ .../com/taobao/weex/bridge/WXBridgeManager.java | 2 +- .../java/com/taobao/weex/bridge/WXParams.java | 12 +- .../java/com/taobao/weex/utils/WXFileUtils.java | 31 +++++ .../taobao/weex/utils/WXSoInstallMgrSdk.java | 3 + .../jsengine/multiprocess/WeexJSConnection.cpp | 50 ++++---- .../android/jsengine/multiprocess/WeexProxy.cpp | 116 +++++++++++-------- .../android/jsengine/multiprocess/WeexProxy.h | 1 + .../Source/core/render/node/render_object.h | 2 +- 9 files changed, 208 insertions(+), 80 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java index 758494e..86d70c4 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java +++ b/android/sdk/src/main/java/com/taobao/weex/WXEnvironment.java @@ -27,19 +27,26 @@ import android.graphics.Typeface; import android.os.Environment; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.Log; import com.taobao.weex.common.WXConfig; import com.taobao.weex.utils.FontDO; import com.taobao.weex.utils.LogLevel; import com.taobao.weex.utils.TypefaceUtil; +import com.taobao.weex.utils.WXFileUtils; import com.taobao.weex.utils.WXLogUtils; import com.taobao.weex.utils.WXSoInstallMgrSdk; import com.taobao.weex.utils.WXUtils; +import org.w3c.dom.Text; + import java.io.File; +import java.io.IOException; import java.util.HashMap; import java.util.Map; +import dalvik.system.PathClassLoader; + public class WXEnvironment { public static final String OS = "android"; @@ -100,6 +107,9 @@ public class WXEnvironment { private static String sGlobalFontFamily; public static final String CORE_SO_NAME = "weexcore"; + public static final String CORE_JSS_SO_NAME = "weexjss"; + + private static String CORE_JSS_SO_PATH = null; private static Map<String, String> options = new HashMap<>(); static { @@ -334,4 +344,65 @@ public class WXEnvironment { openDebugLog = false; } } + + public static String findSoPath(String libName) { + final String libPath = ((PathClassLoader) (WXEnvironment.class.getClassLoader())).findLibrary(libName); + WXLogUtils.e(libName + "'s Path is" + libPath); + return libPath; + } + + public static String getCacheDir() { + final Application application = getApplication(); + if (application == null || application.getApplicationContext() == null) + return null; + return application.getApplicationContext().getCacheDir().getPath(); + } + + public static boolean extractSo() { + File sourceFile = new File(getApplication().getApplicationContext().getApplicationInfo().sourceDir); + final String cacheDir = getCacheDir(); + if (sourceFile.exists() && !TextUtils.isEmpty(cacheDir)) { + try { + WXFileUtils.extractSo(sourceFile.getAbsolutePath(), cacheDir); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + return false; + } + + private static String findLibJssRealPath() { + String soPath = findSoPath(CORE_JSS_SO_NAME); + String realName = "lib" + CORE_JSS_SO_NAME + ".so"; + if (TextUtils.isEmpty(soPath)) { + String cacheDir = getCacheDir(); + if (TextUtils.isEmpty(cacheDir)) { + return ""; + } + if (cacheDir.indexOf("/cache") > 0) { + soPath = new File(cacheDir.replace("/cache", "/lib"), realName).getAbsolutePath(); + } + } + final File soFile = new File(soPath); + if (soFile.exists()) + return soPath; + else { + //unzip from apk file + final boolean success = extractSo(); + if (success) + return new File(getCacheDir(), realName).getAbsolutePath(); + } + return ""; + } + + public static String getLibJssRealPath() { + if(TextUtils.isEmpty(CORE_JSS_SO_PATH)) { + CORE_JSS_SO_PATH = findLibJssRealPath(); + WXLogUtils.e("findLibJssRealPath " + CORE_JSS_SO_PATH); + } + + return CORE_JSS_SO_PATH; + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java index 58b18a0..5d20f14 100644 --- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java +++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java @@ -30,7 +30,6 @@ import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.v4.util.ArrayMap; import android.text.TextUtils; -import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -1795,6 +1794,7 @@ public class WXBridgeManager implements Callback, BactchExecutor { wxParams.setShouldInfoCollect(config.get("infoCollect")); wxParams.setLogLevel(config.get(WXConfig.logLevel)); wxParams.setUseSingleProcess(isUseSingleProcess ? "true" : "false"); + wxParams.setLibJssPath(WXEnvironment.getLibJssRealPath()); String appName = config.get(WXConfig.appName); if (!TextUtils.isEmpty(appName)) { wxParams.setAppName(appName); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java index 5a7081d..8bc182c 100644 --- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java +++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXParams.java @@ -18,8 +18,6 @@ */ package com.taobao.weex.bridge; -import android.util.Log; - import com.taobao.weex.utils.WXLogUtils; import java.util.Map; @@ -39,6 +37,7 @@ public class WXParams { private String needInitV8; private String cacheDir; private String useSingleProcess; + private String libJssPath; private Map<String, String> options; @@ -171,4 +170,13 @@ public class WXParams { this.needInitV8 = "0"; } } + + public String getLibJssPath() { + WXLogUtils.e("getLibJssPath is running " + libJssPath); + return libJssPath; + } + + public void setLibJssPath(String libJssPath) { + this.libJssPath = libJssPath; + } } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java b/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java index 7b354f1..7118ed2 100644 --- a/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java +++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXFileUtils.java @@ -22,6 +22,7 @@ import android.content.Context; import android.text.TextUtils; import android.util.Base64; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -34,6 +35,9 @@ import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; public class WXFileUtils { @@ -178,4 +182,31 @@ public class WXFileUtils { return ""; } } + + public static void extractSo(String apkFile, String path) throws IOException { + ZipFile zip = new ZipFile(apkFile); + InputStream zipInputStream = new BufferedInputStream(new FileInputStream(apkFile)); + ZipInputStream zin = new ZipInputStream(zipInputStream); + ZipEntry zipEntry; + while ((zipEntry = zin.getNextEntry()) != null) { + if(zipEntry.isDirectory()){ + continue; + } + if(zipEntry.getName().contains("lib/armeabi/") && zipEntry.getName().contains("weex")){ + String[] fileNames = zipEntry.getName().split("/"); + String fileName = fileNames[fileNames.length - 1]; + InputStream inputStream = zip.getInputStream(zipEntry); + byte[] data = new byte[1024]; + FileOutputStream outputStream =new FileOutputStream(path + "/" + fileName); + while (inputStream.read(data) != -1) { + outputStream.write(data); + } + outputStream.close(); + + } + } + zin.closeEntry(); + } + + } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java ---------------------------------------------------------------------- diff --git a/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java b/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java index c493937..09c5077 100644 --- a/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java +++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXSoInstallMgrSdk.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.os.Build; import android.text.TextUtils; +import android.util.Log; import com.taobao.weex.BuildConfig; import com.taobao.weex.IWXStatisticsListener; @@ -238,6 +239,8 @@ public class WXSoInstallMgrSdk { } inputStream.close(); outputStream.close(); + } else { + WXEnvironment.extractSo(); } } } catch (Throwable e) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp ---------------------------------------------------------------------- diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp index 34ac0bd..60667d2 100644 --- a/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp +++ b/weex_core/Source/android/jsengine/multiprocess/WeexJSConnection.cpp @@ -19,6 +19,7 @@ #include "WeexJSConnection.h" #include "ashmem.h" +#include "WeexProxy.h" #include <dirent.h> #include <stdlib.h> #include <sys/stat.h> @@ -35,6 +36,8 @@ #include <errno.h> extern const char *s_cacheDir; +extern const char *g_jssSoPath; +extern const char *g_jssSoName; extern bool s_start_pie; static void doExec(int fd, bool traceEnable, bool startupPie = true); @@ -167,10 +170,7 @@ void printLogOnFile(const char *log) { #endif } -static std::string __attribute__((noinline)) findPath(); - -static void findPath(std::string &executablePath, std::string &icuDataPath) { - unsigned long target = reinterpret_cast<unsigned long>(__builtin_return_address(0)); +static void findIcuDataPath(std::string &icuDataPath) { FILE *f = fopen("/proc/self/maps", "r"); if (!f) { return; @@ -181,30 +181,9 @@ static void findPath(std::string &executablePath, std::string &icuDataPath) { if (icuDataPath.empty() && strstr(line, "icudt")) { icuDataPath.assign(strstr(line, "/")); icuDataPath = icuDataPath.substr(0, icuDataPath.length() - 1); - continue; } - char *end; - unsigned long val; - errno = 0; - val = strtoul(line, &end, 16); - if (errno) - continue; - if (val > target) - continue; - end += 1; - errno = 0; - val = strtoul(end, &end, 16); - if (errno) - continue; - if (val > target) { - executablePath.assign(strstr(end, "/")); - std::size_t found = executablePath.rfind('/'); - if (found != std::string::npos) { - executablePath = executablePath.substr(0, found); - } - } - if (!executablePath.empty() - && !icuDataPath.empty()) { + + if (!icuDataPath.empty()) { break; } } @@ -257,13 +236,24 @@ std::unique_ptr<const char *[]> EnvPBuilder::build() { void doExec(int fd, bool traceEnable, bool startupPie) { std::string executablePath; std::string icuDataPath; - findPath(executablePath, icuDataPath); + findIcuDataPath(icuDataPath); + if(g_jssSoPath != nullptr) { + executablePath = g_jssSoPath; + } + if (executablePath.empty()) { + executablePath = WeexCore::WeexProxy::findLibJssSoPath(); + } #if PRINT_LOG_CACHEFILE std::ofstream mcfile; mcfile.open(logFilePath, std::ios::app); mcfile << "jsengine WeexJSConnection::doExec executablePath:" << executablePath << std::endl; mcfile << "jsengine WeexJSConnection::doExec icuDataPath:" << icuDataPath << std::endl; #endif + std::string::size_type pos = std::string::npos; + std::string libName = g_jssSoName; + pos = executablePath.find(libName); + if (pos != std::string::npos) { + executablePath.replace(pos, libName.length(), ""); if (executablePath.empty()) { LOGE("executablePath is empty"); @@ -274,7 +264,9 @@ void doExec(int fd, bool traceEnable, bool startupPie) { #endif return; - } + } else { + LOGE("executablePath is %s", executablePath.c_str()); + }} if (icuDataPath.empty()) { LOGE("icuDataPath is empty"); #if PRINT_LOG_CACHEFILE http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp ---------------------------------------------------------------------- diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp index f523ea2..f6a56e8 100644 --- a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp +++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.cpp @@ -31,6 +31,8 @@ #include <core/manager/weex_core_manager.h> const char *s_cacheDir; +const char *g_jssSoPath = nullptr; +const char *g_jssSoName = "libweexjss.so"; bool s_start_pie = true; static IPCSender *sSender; @@ -112,7 +114,9 @@ namespace WeexCore { return param; } - inline void addParamsFromJArgs(std::vector<VALUE_WITH_TYPE *>& params, VALUE_WITH_TYPE *param, std::unique_ptr<IPCSerializer>& serializer, JNIEnv* env, jobject jArg){ + inline void addParamsFromJArgs(std::vector<VALUE_WITH_TYPE *> ¶ms, VALUE_WITH_TYPE *param, + std::unique_ptr<IPCSerializer> &serializer, JNIEnv *env, + jobject jArg) { jfieldID jTypeId = env->GetFieldID(jWXJSObject, "type", "I"); jint jTypeInt = env->GetIntField(jArg, jTypeId); @@ -152,7 +156,7 @@ namespace WeexCore { jbyteArray dataArray = (jbyteArray) jDataObj; if (js_server_api_functions != nullptr) { param->type = ParamsType::BYTEARRAY; - jbyte* data = env->GetByteArrayElements(dataArray, 0); + jbyte *data = env->GetByteArrayElements(dataArray, 0); size_t length = env->GetArrayLength(dataArray); param->value.byteArray = genWeexByteArray((const char *) data, length); } else { @@ -166,14 +170,14 @@ namespace WeexCore { } } - if (param != nullptr){ + if (param != nullptr) { params.push_back(param); } env->DeleteLocalRef(jDataObj); } - inline void freeParams(std::vector<VALUE_WITH_TYPE *>& params){ + inline void freeParams(std::vector<VALUE_WITH_TYPE *> ¶ms) { for (auto ¶m : params) { if (param->type == ParamsType::STRING || param->type == ParamsType::JSONSTRING) { @@ -268,7 +272,8 @@ namespace WeexCore { Bridge_Impl_Android::getInstance()->setGlobalRef(jThis); WeexCoreManager::getInstance()->setPlatformBridge(Bridge_Impl_Android::getInstance()); WeexCoreManager::getInstance()->setJSBridge(new JSBridge()); - WeexCoreManager::getInstance()->SetMeasureFunctionAdapter(new MeasureFunctionAdapterImplAndroid()); + WeexCoreManager::getInstance()->SetMeasureFunctionAdapter( + new MeasureFunctionAdapterImplAndroid()); std::unique_ptr<IPCSerializer> serializer(createIPCSerializer()); const std::vector<INIT_FRAMEWORK_PARAMS *> &initFrameworkParams = initFromParam(env, script, @@ -374,7 +379,7 @@ namespace WeexCore { } jobject jArg = env->GetObjectArrayElement(jargs, i); - addParamsFromJArgs(params, param,serializer, env, jArg); + addParamsFromJArgs(params, param, serializer, env, jArg); env->DeleteLocalRef(jArg); } @@ -418,7 +423,7 @@ namespace WeexCore { return true; } - static std::string findPath() { + std::string WeexProxy::findLibJssSoPath() { std::string executablePath = ""; unsigned long target = reinterpret_cast<unsigned long>(__builtin_return_address(0)); FILE *f = fopen("/proc/self/maps", "r"); @@ -455,7 +460,44 @@ namespace WeexCore { } } fclose(f); - return executablePath; + LOGE("find so path: %s", executablePath.c_str()); + std::string::size_type pos = std::string::npos; + // dynamic deploy + if (!executablePath.empty() && executablePath.find(".maindex") != std::string::npos) { + std::string libs[] = {"/opt", "/oat/arm"}; + auto libsCount = sizeof(libs) / sizeof(std::string); + for (int i = 0; i < libsCount; ++i) { + auto lib = libs[i]; + pos = executablePath.find(lib); + if (pos != std::string::npos) { + executablePath.replace(pos, lib.length(), "/lib"); + break; + } + } + } + std::string soPath = executablePath + "/" + g_jssSoName; + // ------------------------------------------------- + // ------------------------------------------------- + if (access(soPath.c_str(), 00) == 0) { + return soPath; + } else { + const char *error = soPath.c_str(); + LOGE("so path: %s is not exsist, use full package lib", error); + executablePath = s_cacheDir; + std::string lib = "/cache"; + if ((pos = soPath.find(lib)) != std::string::npos) { + executablePath.replace(pos, lib.length(), "/lib"); + } + soPath = executablePath + "/" + g_jssSoName; + if (access(soPath.c_str(), 00) != 0) { + LOGE("so path: %s is not exsist", soPath.c_str()); + reportNativeInitStatus("-1004", error); + //return false; + //use libweexjss.so directly + soPath = g_jssSoName; + } + return soPath; + } } static WEEX_CORE_JS_API_FUNCTIONS *getWeexCoreApiFunctions() { @@ -510,44 +552,12 @@ namespace WeexCore { // ----------------------------------------------- // use find path to get lib path // use set path is better idea, should change in future - soPath = findPath(); - - std::string::size_type pos = std::string::npos; - LOGE("find so path: %s", soPath.c_str()); - // dynamic deploy - if (!soPath.empty() && soPath.find(".maindex") != std::string::npos) { - std::string libs[] = {"/opt", "/oat/arm"}; - auto libsCount = sizeof(libs) / sizeof(std::string); - for (int i = 0; i < libsCount; ++i) { - auto lib = libs[i]; - pos = soPath.find(lib); - if (pos != std::string::npos) { - soPath.replace(pos, lib.length(), "/lib"); - break; - } - } - soPath += "/libweexjss.so"; - } else { - soPath += "libweexjss.so"; + if (g_jssSoPath != nullptr) { + soPath = g_jssSoPath; } - // ------------------------------------------------- - // ------------------------------------------------- - if (access(soPath.c_str(), 00) != 0) { - LOGE("so path: %s is not exsist, use full package lib", soPath.c_str()); - const char *error = soPath.c_str(); - soPath = s_cacheDir; - std::string lib = "/cache"; - if ((pos = soPath.find(lib)) != std::string::npos) { - soPath.replace(pos, lib.length(), "/lib"); - } - soPath += "/libweexjss.so"; - if (access(soPath.c_str(), 00) != 0) { - LOGE("so path: %s is not exsist", soPath.c_str()); - reportNativeInitStatus("-1004", error); - //return false; - //use libweexjss.so directly - soPath = "libweexjss.so"; - } + + if (soPath.empty()) { + soPath = findLibJssSoPath(); } LOGE("final executablePath:%s", soPath.c_str()); @@ -555,7 +565,7 @@ namespace WeexCore { void *handle = dlopen(soPath.c_str(), RTLD_NOW); if (!handle) { const char *error = dlerror(); - LOGE("load libweexjss.so failed,error=%s\n", error); + LOGE("load %s failed,error=%s\n", g_jssSoName, error); reportNativeInitStatus("-1005", error); // try again use current path dlclose(handle); @@ -645,6 +655,18 @@ namespace WeexCore { g_use_single_process = strstr(use_single_process, "true") != nullptr; } + jmethodID m_get_jss_so_path = env->GetMethodID(c_params, "getLibJssPath", + "()Ljava/lang/String;"); + if (m_get_jss_so_path != nullptr) { + jobject j_get_jss_so_path = env->CallObjectMethod(params, m_get_jss_so_path); + if (j_get_jss_so_path != nullptr) { + g_jssSoPath = env->GetStringUTFChars( + (jstring) (j_get_jss_so_path), + nullptr); + LOGE("g_jssSoPath is %s ", g_jssSoPath); + } + } + jmethodID m_osVersion = env->GetMethodID( c_params, "getOsVersion", "()Ljava/lang/String;"); jobject osVersion = env->CallObjectMethod(params, m_osVersion); @@ -971,7 +993,7 @@ namespace WeexCore { WeexJSResult jsResultData = js_server_api_functions->funcExeJSWithResult( instanceidChar.getChars(), namespaceChar, functionChar.getChars(), params); freeParams(params); - jbyteArray array = newJByteArray(env, jsResultData.data, jsResultData.length); + jbyteArray array = newJByteArray(env, jsResultData.data, jsResultData.length); WeexJSResultDataFree(jsResultData); return array; } else { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h ---------------------------------------------------------------------- diff --git a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h index 0699d60..d179c77 100644 --- a/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h +++ b/weex_core/Source/android/jsengine/multiprocess/WeexProxy.h @@ -63,6 +63,7 @@ public: static bool execJSService(JNIEnv *env, jobject object, jstring script); + static std::string findLibJssSoPath(); static bool execJS(JNIEnv *env, jobject jthis, jstring jinstanceid, jstring jnamespace, jstring jfunction, jobjectArray jargs); http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/1e715624/weex_core/Source/core/render/node/render_object.h ---------------------------------------------------------------------- diff --git a/weex_core/Source/core/render/node/render_object.h b/weex_core/Source/core/render/node/render_object.h index 8f50bff..1a6352c 100644 --- a/weex_core/Source/core/render/node/render_object.h +++ b/weex_core/Source/core/render/node/render_object.h @@ -32,7 +32,7 @@ #define convert_render_object_to_long(render) ((jlong)((intptr_t)render)) #define convert_long_to_render_object(ptr) \ - (static_cast<RenderObject *>((intptr_t)ptr)) + ((RenderObject *)((intptr_t)ptr)) namespace WeexCore {
