JNI编程四:java跟JNI字符串传递

目录


前言

java中的中文字符使用的编码方式是根据系统默认编码方式,一般使用的是GB2312的编码方式,jni中的中文字符采用的是unicode的编码方式。所以在字符传递的时候会出现乱码情况。

一、java层向jni层传递中文字符串的转码操作

java层向jni传递中文字符的时候,我们可以利用windows.h给我们封装好的函数来操作。

JniMain.java

java 复制代码
public class JniMain {

    static{
        System.loadLibrary("JNI_Demo1");
    }
    
    //----------------------向jni层传递字符串--------------------
    public native String chineseChars(String str);
    //---------------------------------------------
    
    
    public static void main(String[] args) {
        
        JniMain jm = new JniMain();
    
        String str = jm.chineseChars("德玛西亚"); 
        
        System.out.println("java "+ str);
        
    }
}

jni_impl.c

java 复制代码
#include "stdafx.h"

#include "JniMain.h"
#include <string.h>
#include <Windows.h>

/*
* Class:     JniMain
* Method:    chineseChars
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JniMain_chineseChars
(JNIEnv * env, jobject jobj, jstring in){
    
        //iscp代表的是string转char的时候是否从新开辟的内存copy的一份
    jboolean iscp;
    char * c_str = (*env)->GetStringChars(env, in, &iscp);
    if (iscp == JNI_TRUE)
    {
        printf("is copy: JNI_TRUE\n");
    }
    else if (iscp == JNI_FALSE)
    {
        printf("is copy: JNI_FALSE\n");
    }

    int length = (*env)->GetStringLength(env, in);
    const jchar * jcstr = (*env)->GetStringChars(env, in, NULL);
    if (jcstr == NULL) {
        return NULL;
    }
    //jchar -> char
    char * rtn = (char *)malloc(sizeof(char)* 2 * (length + 1));
    memset(rtn, 0, sizeof(char)* 2 * (length + 1));
    int size = 0;
    //windows提供的字符串转码的操作
    size = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)jcstr, length, rtn, sizeof(char)* 2 * (length + 1), NULL, NULL);
    /*if (size <= 0)
    {
    printf("size: 0 \n", rtn);
    return NULL;
    }*/
    printf("jni string: %s\n", rtn);
    if (rtn != NULL) {
        free(rtn);
        rtn = NULL;
    }
    if (iscp == JNI_TRUE)
    {
        (*env)->ReleaseStringChars(env, in, c_str);// JVM 使用。通知JVM c_str 所指的空间可以释放了
    }

      return NULL;
}

jni_impl.c的JNICALL Java_JniMain_chineseChars函数是将java层传递的字符串能转换成jni能识别的字符串。执行结果:


二、jni层向java层传递中文字符串的转码操作

jni层向java层传递字符串时可以使用JNIEnv所指向的结构体封装的函数来调用java中String对象封装的字符串转码功能。

jni_impl.c

java 复制代码
#include "stdafx.h"

#include "JniMain.h"
#include <string.h>
#include <Windows.h>

/*
* Class:     JniMain
* Method:    chineseChars
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JniMain_chineseChars
(JNIEnv * env, jobject jobj, jstring in){
    
       char *c_str2 = "诺克萨斯";
    jclass str_cls = (*env)->FindClass(env, "java/lang/String");
    jmethodID jmid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");
    
    //jstring -> jbyteArray
    jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str2));
    // 将Char * 赋值到 bytes
    (*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str2), c_str2);
    jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    return (*env)->NewObject(env, str_cls, jmid, bytes, charsetName);

}

其实上面的代码就是jvm反射调用java中的 new String("诺克萨斯","GB2312")


相关推荐
田一一一6 天前
Android framework 中间件开发(三)
android·中间件·framework·jni
缘来的精彩2 个月前
Android JNI性能优化与字符串加载实践
android·性能优化·jni·androidndk
CYRUS STUDIO3 个月前
使用 AndroidNativeEmu 调用 JNI 函数
android·汇编·arm开发·arm·逆向·jni
aworkholic5 个月前
opencv sdk for java中提示无stiching模块接口的问题
java·c++·opencv·jni·opencv4android·stiching
Maxwellhang6 个月前
【java-ffmpeg】java 内存测试和集成
java·ffmpeg·jni
CYRUS STUDIO7 个月前
frida脚本,自动化寻址JNI方法
android·运维·自动化·逆向·移动安全·jni·frida
胡耀超7 个月前
JNI(Java Native Interface)和NIO(New Input/Output)是什么?
java·开发语言·nio·jni
穷人小水滴8 个月前
Android (rust) vulkan (JNI) 画一个三角形: VulkanSurfaceView 初始化
android·开发语言·rust·gpu·jni·vulkan·surfaceview
偶是老李头8 个月前
Android - NDK:在Jni中打印Log信息
android·jni·android ndk log·jni log
菠萝加点糖9 个月前
Android JNI 设置环境变量
android·环境变量·jni