JNI的快速入门实践
JNI基本操作
目的
本文为JNI HelloWorld教程,阐述编写java本地调用的一般方法流程,可用于pmdk的API调用。
环境准备
- vim 或其他IDE
- Linux运行环境包含gcc
- JDK 8
简单来说,是台Linux机器都行,装过Insight的机器都有JDK环境
流程
Java端代码
先看下普通的HelloWorld
创建文件 HelloWorld.java(文件名需与类名一致)
public class HelloWorld {
public void sayHello(String message) {
System.out.println(message);
}
public static void main(String []args) {
new HelloWorld().sayHello("Hello World");
}
}
- JNI版本的HelloWorld
创建文件 JNIDemo.java(文件名需与类名一致)
public class JNIDemo {
//定义一个方法,该方法在C中实现
public native void sayHelloC();
public static void main(String[] args) {
System.loadLibrary("testJNI");
JNIDemo jniDemo = new JNIDemo();
jniDemo.sayHelloC();
}
}
- 利用此java类生成c头文件
javah -classpath . -jni com.insight.test.JNIDemo
如果没有写package则执行(像本文所述就没写包名):
javah -classpath . -jni JNIDemo
可见生成对应的头文件。
.h头文件截图
native代码
- 编写c/c++文件
#include "JNIDemo.h"
#include <iostream>
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_insight_test_JNIDemo_sayHelloC
(JNIEnv *, jobject) {
printf("Hi,this is C++ print! \n");
}
注意了,"JNIDemo.h
"就是第2步生成的那个头文件,与c代码放在同一目录下。
- 编译生成动态链接库
生成.o
文件的话执行:g++ -c testJNI.cpp
(仅记录一下,不需要执行这一个操作!)
生成动态库.so文件:(copy这个↓↓)
g++ -shared testJNI.cpp -o libtestJNI.so -fPIC
如果未指定-o参数, 则默认生成的库文件是a.out
- (可选)将libtestJNI.so拷贝到库路径下,如
/usr/lib64
- 运行Java类
java -cp . com.insight.test.JNIDemo
,在根目录执行,可以看到输出为cpp文件所定义的方法内容。
“Hi,this is C++ print!”:heart:
OK了 :smile:。
Debug
Q:运行Java程序报错:Error:Could not find or load main class XXXX。如何解决?
A:代码HelloWorld级别都不能运行成功,不是代码的问题。
检查对比可运行的环境得知,出错的机器包含了CLASSPATH变量,该环境变量指向JAVA_HOME/lib。
正常运行的环境里没有设置这个变量,因此执行unset CLASSPATH
java ClassName
即可正常执行!!
Q:报错缺少jni.h,jni_md.h,或找不到?
A: 不要使用拷贝该文件的方式,配置CPATH环境变量来实现。
Q: 有package的类怎么直接编写执行?
A:按包名层级创建文件夹,把类文件放进去。执行时需要到根目录,执行java -cp . com.insight.test.JNIDemo
,这样可包含类路径。否则出现Error: Could not find or load main class com.insight.test.JNIDemo
Q: 怎么编译动态链接库.so文件或.o文件?
A: 见流程4。结尾.o的文件不是必须要有的。
点:Java本地调用、JNI入门
线:Java
面:编程技术