使用NDK构建JNI项目时返回int正常,含if语句报JNI错误求助
JNI错误修复与AAR核心功能实现方案
一、当前JNI错误的根源与修复
错误原因
- 非法类型转换:直接把C语言字符串强转为
jstring(比如(jstring)"stri")是完全错误的操作——jstring是JNI虚拟机维护的引用类型,不能通过强制类型转换创建,必须通过JNIEnv提供的API生成。 - 字符串比较逻辑错误:
text != str比较的是两个jstring的引用地址,而非字符串实际内容,完全达不到你想要的字符串相等判断效果。
修复后的CPP代码
// Created by flsor on 2022-10-06. // #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> #include<kr_go_murldc2_murldc2.h> JNIEXPORT jstring JNICALL Java_kr_go_murldc2_murldc2_print_1ndk (JNIEnv *env, jobject thiz, jstring text) { // 将Java字符串转为C风格UTF-8字符串 const char* input_str = env->GetStringUTFChars(text, nullptr); const char* target_str = "stri"; // 比较字符串实际内容 if(strcmp(input_str, target_str) != 0){ // 通过JNI API合法创建jstring jstring result = env->NewStringUTF("notsame"); // 释放C字符串资源,避免内存泄漏 env->ReleaseStringUTFChars(text, input_str); return result; } // 释放资源 env->ReleaseStringUTFChars(text, input_str); return text; } JNIEXPORT jint JNICALL Java_kr_go_murldc2_murldc2_add_1ndk (JNIEnv *env, jobject thiz, jint a,jint b) { return a+b+3; }
修复说明
- 使用
env->GetStringUTFChars()完成Java字符串到C字符串的转换,使用后必须调用env->ReleaseStringUTFChars()释放资源,避免内存泄漏。 - 用
strcmp()比较字符串实际内容,替代无效的引用地址比较。 - 所有返回给Java层的
jstring,必须通过env->NewStringUTF()创建,确保是JNI虚拟机认可的合法引用。
二、CPP中实现HTTP通信与HTML解析(提高反编译难度)
要将核心逻辑放在CPP层以提升AAR的反破解难度,可采用以下方案:
1. HTTP通信:集成libcurl
libcurl是成熟的跨平台HTTP客户端库,支持多种协议,适配NDK环境:
- 下载预编译的NDK版libcurl,或自行编译适配目标Android ABIs。
- 在
Android.mk中添加libcurl的链接配置:LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # 引入预编译的libcurl库 LOCAL_MODULE := curl LOCAL_SRC_FILES := path/to/your/libcurl.so # 替换为实际路径 include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := helloNdk FILES := hello_ndk.cpp LOCAL_SRC_FILES := $(FILES) LOCAL_LDLIBS := -llog # 链接libcurl库 LOCAL_SHARED_LIBRARIES := curl include $(BUILD_SHARED_LIBRARY) - 在CPP代码中调用libcurl API发起GET/POST请求,获取HTTP响应内容。
2. HTML解析:使用tinyxml2或libxml2
- tinyxml2:轻量级XML/HTML解析库,代码量小,易集成,适合移动端场景。
- libxml2:功能全面的XML解析库,支持HTML解析,Android系统本身也依赖相关组件。
- 将解析库的源码或预编译库集成到NDK项目中,在CPP层完成HTML内容解析,提取目标数据后通过JNI返回给Java层。
3. 关键注意事项
- 所有核心逻辑(请求发起、HTML解析)均在CPP层实现,Java层仅保留简单调用逻辑,最大化反编译难度。
- 严格遵循JNI引用规范,避免出现本地引用失效、内存泄漏等问题。
- 打包AAR时,确保所有依赖的SO库(libcurl、解析库、helloNdk)都被正确打包进AAR包内。
内容的提问来源于stack exchange,提问作者구병희
相关产品推荐
相关产品推荐

