文章目录
- 1 Java 代码
- 2 C 代码
- 3 总结
- 3.1 获取参数
- 3.2 调用方法

1 Java 代码
JNI 代码
package com.karashok;import java.util.UUID;public class JNIDemo {/*** 获取静态方法返回值*/public static native String sayHello();/*** 获取方法返回值*/public native String sayWorld();/*** 修改属性 s*/public native void setS();/*** 修改静态属性 ss* @return*/public native static void setSs();private String s = "qwer";private static String ss = "asdf";public static String getSs() {return ss;}public String getS() {return s;}private long getTime() {return System.currentTimeMillis();}private static String getUUid() {return UUID.randomUUID().toString();}
}
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("静态方法返回值: " + JNIDemo.sayHello());System.out.println("----- 获取方法返回值 -----");System.out.println("方法返回值: " + demo.sayWorld());System.out.println("----- 修改静态属性 -----");System.out.println("静态属性修改前: " + JNIDemo.getSs());JNIDemo.setSs();System.out.println("静态属性修改后: " + JNIDemo.getSs());System.out.println("----- 修改属性 -----");System.out.println("属性修改前: " + demo.getS());demo.setS();System.out.println("属性修改后: " + demo.getS());}
}
2 C 代码
需要将 jni.h
、jni_md.h
两个头文件放到包中。
头文件代码
#include "jni.h"
#include <string.h>#ifndef DEMO_LIBRARY_H
#define DEMO_LIBRARY_H/** Class: com_karashok_JNIDemo* Method: sayHello* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayHello
(JNIEnv *, jclass);/** Class: com_karashok_JNIDemo* Method: sayWorld* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayWorld
(JNIEnv *, jobject);/** Class: com_karashok_JNIDemo* Method: setS* Signature: ()Ljava/lang/String;*/
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setS
(JNIEnv *, jobject);/** Class: com_karashok_JNIDemo* Method: setSs* Signature: ()Ljava/lang/String;*/
JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setSs
(JNIEnv *, jclass);#endif //DEMO_LIBRARY_H
代码
#include "library.h"JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayHello(JNIEnv *jniEnv, jclass jcls) {jmethodID mid = (*jniEnv)->GetStaticMethodID(jniEnv,jcls,"getUUid","()Ljava/lang/String;");jstring jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv,jcls,mid);char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);printf("UUID is: %s\n",str);return (*jniEnv)->NewStringUTF(jniEnv,"Hello ");
}JNIEXPORT jstring JNICALL Java_com_karashok_JNIDemo_sayWorld(JNIEnv *jniEnv, jobject jobj) {jclass jcls = (*jniEnv)->GetObjectClass(jniEnv,jobj);jmethodID mid = (*jniEnv)->GetMethodID(jniEnv,jcls,"getTime","()J");jlong jl = (*jniEnv)->CallLongMethod(jniEnv,jobj,mid);printf("Time is: %ld\n",jl);return (*jniEnv)->NewStringUTF(jniEnv,"World!\n");
}JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setS(JNIEnv *jniEnv, jobject jobj) {jclass jcls = (*jniEnv)->GetObjectClass(jniEnv,jobj);jfieldID fid = (*jniEnv)->GetFieldID(jniEnv,jcls,"s","Ljava/lang/String;");jstring jstr = (*jniEnv)->GetObjectField(jniEnv,jobj,fid);char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);char newStr[20] = "Demo ";strcat(newStr,str);jstring newjstr = (*jniEnv)->NewStringUTF(jniEnv,newStr);(*jniEnv)->SetObjectField(jniEnv,jobj,fid,newjstr);}JNIEXPORT void JNICALL Java_com_karashok_JNIDemo_setSs(JNIEnv *jniEnv, jclass jcls) {jfieldID fid = (*jniEnv)->GetStaticFieldID(jniEnv,jcls,"ss","Ljava/lang/String;");jstring jstr = (*jniEnv)->GetStaticObjectField(jniEnv,jcls,fid);char *str = (*jniEnv)->GetStringUTFChars(jniEnv,jstr,JNI_FALSE);char newStr[20] = "Demo ";strcat(newStr,str);jstring newjstr = (*jniEnv)->NewStringUTF(jniEnv,newStr);(*jniEnv)->SetStaticObjectField(jniEnv,jcls,fid,newjstr);
}
3 总结
3.1 获取参数
- 获取 class 对象
- 获取属性的 fieldID
- 获取属性值
- 将属性值转化为 c 的值
3.2 调用方法
- 获取 class 对象
- 获取方法的 methodID
- 调用方法获取返回值
- 将返回值转化为 c 的值
注意: C 调用 Java 方法是不区分权限的,也就是说 public 的属性/方法和 private 的属性/方法是一样的。
获取方法签名:javap -s -p com.karashok.JNIDemo
,一定要尽到相应 src 的根目录下而不是类的目录。