JNI记录
第一次尝试JNI,文件夹共有以下几个文件:
Native.java
Native.class
NativeCpp.h
jni.cpp
jni.o
jni.so
test.cpp
test.o
test.so
-
先规划Native.java中要用c++实现的方法,用native关键字修饰这些方法(只要声明),javac成class文件,javah生成.h,.h中就有了需要用C++实现的函数的声明;
-
写代码实现这些函数,并且打包成so文件(linux下),在java代码中load,就可以运行了
-
在jni.cpp中include了NativeCpp.h,在jni.cpp中实现了NativeCpp.h声明的方法;但是test.cpp中没有include,而是直接把NativeCpp.h中的内容复制过去,并把所有函数声明的地方改成了实现;
两个同样打包成so文件,给java调用,都可以运行。
代码
HelloWorld.java
HelloWorld.h
HelloWorld.cpp
先写 HelloWorld.java
public class HelloWorld{
public native void sayHello(String string);
public static void main(String[] args) throws InterruptedException{
//指定要使用的库文件
System.load("/home/shuai/桌面/JNI/HelloWorld.so");
HelloWorld jni = new HelloWorld();
jni.sayHello("JNI!");
}
}
运行命令
javac HelloWorld.java
javah -jni HelloWorld
生成HelloWorld.h,内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: sayHello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloWorld_sayHello
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
再写 HelloWorld.cpp(native方法实现)
#include<jni.h>
#include"HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_sayHello
(JNIEnv * env, jobject arg, jstring instring)
{
const jbyte *str = (const jbyte*) env->GetStringUTFChars(instring, JNI_FALSE);
printf("Hello, %s\n", str);
env->ReleaseStringUTFChars(instring, (const char *)str);
}
生成库文件并执行类
gcc -fPIC -c HelloWorld.cpp -I /usr/local/jdk1.8.0_281/include -I /usr/local/jdk1.8.0_281/include/linux (大写字母i)
gcc -shared HelloWorld.o -o HelloWorld.so
java HelloWorld
最后输出Hello, JNI!
几个注意的点:
-
命令:
javac javah -jni (class) gcc -fPIC -c [cpp文件] -I [jdk路径/include] -I [jdk路径/include/linux] (大写字母i) gcc -shared [.o文件] -o [.so文件]
-
在调用方法的地方,要使用
System.load()
或者System.loadLibrary()
方法来加载so库,load()方法发的参数是绝对路径,loadLibrary()方法的参数是so文件名,但一定要在java.library.path中;
可以用System.out.println(System.getProperty("java.library.path"))
来查看path值