You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NDK构建JNI项目时返回int正常,含if语句报JNI错误求助

JNI错误修复与AAR核心功能实现方案

一、当前JNI错误的根源与修复

错误原因

  1. 非法类型转换:直接把C语言字符串强转为jstring(比如(jstring)"stri")是完全错误的操作——jstring是JNI虚拟机维护的引用类型,不能通过强制类型转换创建,必须通过JNIEnv提供的API生成。
  2. 字符串比较逻辑错误: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,提问作者구병희

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 12:30:55