Android中使用Boost转换JSON字符串时应用崩溃问题排查
问题:React Native传递JSON字符串到JNI后应用崩溃无提示
我尝试从React Native的JS代码传递JSON字符串到JNI层读取,但应用启动后直接崩溃,没有任何错误提示。
JS端传递代码
let myJSONString = JSON.stringify({foo: "bar"});
Boost配置的CMakeLists.txt
set(my_boost_dir ${CMAKE_CURRENT_SOURCE_DIR}/libs/ndk_25_boost_1.79.0) set(MY_BOOST_LIBS_DIR ${my_boost_dir}/libs) set(MY_BOOST_INC_DIR ${my_boost_dir}/include) #----------------------------------------- add_library (libboost_container SHARED IMPORTED) set_target_properties( libboost_container PROPERTIES IMPORTED_LOCATION ${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_container.so ) #----------------------------------------- #----------------------------------------- add_library (libboost_json SHARED IMPORTED) set_target_properties( libboost_json PROPERTIES IMPORTED_LOCATION ${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_json.so ) #----------------------------------------- #----------------------------------------- add_library (libboost_system SHARED IMPORTED) set_target_properties( libboost_system PROPERTIES IMPORTED_LOCATION ${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_system.so ) #----------------------------------------- add_library( libboost_chrono SHARED IMPORTED) set_target_properties(libboost_chrono PROPERTIES IMPORTED_LOCATION ${MY_BOOST_LIBS_DIR}/${ANDROID_ABI}/libboost_chrono.so ) #----------------------------------------- include_directories( ${MY_BOOST_INC_DIR} )
JNI读取JSON的代码
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <boost/json.hpp> JNIEXPORT jstring JNICALL Java_com_ca_com_1gen_1lib_1pers_c_1libs_1core_MyStringToJSON_myStringToJSON(JNIEnv *env, jobject instance, jstring myJSONStringEntity_) { const char *myJSONStringEntity = env->GetStringUTFChars(myJSONStringEntity_, 0); // Short alias for this namespace namespace pt = boost::property_tree; // Create a root pt::ptree root; // Load the json file in this ptree pt::read_json(myJSONStringEntity, root); // Read values std::string returnVal = root.get<std::string>("foo", 0); return returnVal; }
错误点分析与解决
1. pt::read_json参数使用错误
boost::property_tree::read_json的第一个参数是文件路径,不是JSON字符串。你直接传入JS传递的字符串,它会把这个字符串当作文件路径去读取,必然找不到文件,触发未捕获异常导致崩溃。
要解析JSON字符串,需用std::istringstream把字符串转为流再传入:
std::istringstream json_stream(myJSONStringEntity); pt::read_json(json_stream, root);
记得包含头文件<sstream>。
2. root.get默认值类型不匹配
root.get<std::string>("foo", 0)里的默认值是整数0,但模板参数是std::string,类型不匹配会引发编译或运行时异常,改为字符串类型的默认值:
std::string returnVal = root.get<std::string>("foo", "default_value");
3. JNI返回值类型错误
你直接返回std::string类型,但JNI函数要求返回jstring,必须用env->NewStringUTF完成转换:
jstring result = env->NewStringUTF(returnVal.c_str());
4. 未释放JNI字符串资源
调用env->GetStringUTFChars后,必须调用env->ReleaseStringUTFChars释放资源,避免内存泄漏:
env->ReleaseStringUTFChars(myJSONStringEntity_, myJSONStringEntity);
5. 未捕获解析异常
Boost Property Tree解析JSON时会抛出异常,JNI层未捕获的异常会直接导致应用崩溃,建议添加try-catch块捕获异常:
6. Boost库未链接到JNI目标
你在CMake中导入了Boost库,但未将它们链接到你的JNI库目标,运行时会找不到符号导致崩溃,需在CMake中添加链接配置:
# 假设你的JNI库目标名为my_jni_lib target_link_libraries(my_jni_lib libboost_container libboost_json libboost_system libboost_chrono android log )
修正后的JNI代码
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <boost/json.hpp> #include <sstream> #include <string> #include <stdexcept> JNIEXPORT jstring JNICALL Java_com_ca_com_1gen_1lib_1pers_c_1libs_1core_MyStringToJSON_myStringToJSON(JNIEnv *env, jobject instance, jstring myJSONStringEntity_) { const char *myJSONStringEntity = env->GetStringUTFChars(myJSONStringEntity_, nullptr); std::string returnVal = "default"; try { namespace pt = boost::property_tree; pt::ptree root; std::istringstream json_stream(myJSONStringEntity); pt::read_json(json_stream, root); returnVal = root.get<std::string>("foo", "default"); } catch (const std::exception& e) { returnVal = e.what(); } env->ReleaseStringUTFChars(myJSONStringEntity_, myJSONStringEntity); return env->NewStringUTF(returnVal.c_str()); }
内容的提问来源于stack exchange,提问作者Program-Me-Rev
相关产品推荐
相关产品推荐

