1 Java 代码
父类代码:
package com.karashok;
public class Human {
public void sayHi() {
System.out.println("Human say Hi!");
}
}
子类代码:
package com.karashok;
public class Man extends Human{
@Override
public void sayHi() {
System.out.println("Man say Hi!");
}
}
JNI 代码:
package com.karashok;
import java.util.Date;
public class JNIDemo {
public Human human = new Man();
/**
* 调用构造方法
* @return
*/
public native Date accessConstructor();
/**
* 调用父类方法
*/
public native void accessSuperMethod();
/**
* 中文字符问题
* @param str
* @return
*/
public native String chineseString(String str);
}
main 代码:
package com.karashok;
public class Main {
static {
System.load("libDemo.dylib");
}
public static void main(String[] args) {
JNIDemo demo = new JNIDemo();
System.out.println("----- 获取构造方法 -----");
System.out.println("方法返回值: " + demo.accessConstructor());
System.out.println("----- 获取父类方法 -----");
demo.accessSuperMethod();
System.out.println("----- 中文字符问题 -----");
System.out.println("方法返回值: " + demo.chineseString("宋喆"));
}
}
2 C 代码:
头文件代码:
#include "jni.h"
#include <string.h>
#ifndef DEMO_LIBRARY_H
#define DEMO_LIBRARY_H
/*
* Class: com_karashok_JNIDemo1
* Method: accessConstructor
* Signature: ()Ljava/util/Date;
*/
JNIEXPORT jobject JNICALL Java_com_karashok_JNIDemo1_accessConstructor
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo1_accessSuperMethod
(JNIEnv *, jobject);
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo1_chineseString
(JNIEnv *, jobject, jstring);
#endif //DEMO_LIBRARY_H
实现代码:
#include "library.h"
/*
* Class: com_karashok_JNIDemo1
* Method: accessConstructor
* Signature: ()Ljava/util/Date;
*/
JNIEXPORT jobject JNICALL Java_com_karashok_JNIDemo1_accessConstructor(JNIEnv *jniEnv, jobject jobj) {
jclass cls = (*jniEnv)->FindClass(jniEnv,"java/util/Date");
jmethodID mid = (*jniEnv)->GetMethodID(jniEnv,cls,"<init>","()V");
jobject dataObj = (*jniEnv)->NewObject(jniEnv,cls,mid);
jmethodID dataMid = (*jniEnv)->GetMethodID(jniEnv,cls,"getTime","()J");
jlong time = (*jniEnv)->CallLongMethod(jniEnv,dataObj,dataMid);
printf("time: %ld\n",time);
return dataObj;
}
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo1_accessSuperMethod(JNIEnv *jniEnv, jobject jobj) {
jclass jcls = (*jniEnv)->GetObjectClass(jniEnv,jobj);
jfieldID manFid = (*jniEnv)->GetFieldID(jniEnv,jcls,"human","Lcom/karashok/Human;");
jobject manObj = (*jniEnv)->GetObjectField(jniEnv,jobj,manFid);
// 正常获取方法
jclass manCls = (*jniEnv)->GetObjectClass(jniEnv,manObj);
jmethodID manMid = (*jniEnv)->GetMethodID(jniEnv,manCls,"sayHi","()V");
(*jniEnv)->CallObjectMethod(jniEnv,manObj,manMid);
// 获取父类方法
jclass humanCls = (*jniEnv)->FindClass(jniEnv,"com/karashok/Human");
jmethodID humanMid = (*jniEnv)->GetMethodID(jniEnv,humanCls,"sayHi","()V");
(*jniEnv)->CallNonvirtualObjectMethod(jniEnv,manObj,humanCls,humanMid);
}
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo1_chineseString(JNIEnv *jniEnv, jobject jobj, jstring jstr) {
char *cStr = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);
printf("Input str: %s\n",cStr);
char *cOutStr = "马蓉与宋喆";
jstring outStr1 = (*jniEnv)->NewStringUTF(jniEnv,cOutStr);
// 如果出现乱码是由于不同电脑的编码格式不同,这个需要指定编码格式
jclass strCls = (*jniEnv)->FindClass(jniEnv,"java/lang/String");
jmethodID constructor_mid = (*jniEnv)->GetMethodID(jniEnv,strCls,"<init>","([BLjava/lang/String;)V");
//
jbyteArray jba = (*jniEnv)->NewByteArray(jniEnv, strlen(cOutStr));
(*jniEnv)->SetByteArrayRegion(jniEnv,jba,0,strlen(cOutStr),cOutStr);
jstring charsetName = (*jniEnv)->NewStringUTF(jniEnv,"GB2312");
jstring outStr2 = (*jniEnv)->NewObject(jniEnv,strCls,constructor_mid,jba,charsetName);
return outStr2;
}
3 总结
- 调用父类方法,其实就是获取父类的类然后用子类对象调用,即可映射到父类方法。
- 中文乱码问题,调用 String 的方法加入编码格式即可。

本文详细介绍了如何在Java和C++通过JNI进行交互,包括创建子类实例、调用父类方法,并解决中文字符串乱码问题。重点展示了JNI的实践应用和跨语言数据传递技巧。
2121

被折叠的 条评论
为什么被折叠?



