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");
    }
}
  1. 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();
    }
}
  1. 利用此java类生成c头文件
javah -classpath . -jni com.insight.test.JNIDemo

如果没有写package则执行(像本文所述就没写包名):

javah -classpath . -jni JNIDemo

可见生成对应的头文件。


.h头文件截图

native代码

  1. 编写c/c++文件
#include "JNIDemo.h"
#include 
#include 

JNIEXPORT void JNICALL Java_com_insight_test_JNIDemo_sayHelloC
(JNIEnv *, jobject) {
    printf("Hi,this is C++ print! \n");
}

注意了,"JNIDemo.h"就是第2步生成的那个头文件,与c代码放在同一目录下。

  1. 编译生成动态链接库

生成.o文件的话执行:g++ -c testJNI.cpp (仅记录一下,不需要执行这一个操作!)

生成动态库.so文件:(copy这个↓↓)

g++ -shared  testJNI.cpp -o libtestJNI.so -fPIC

如果未指定-o参数, 则默认生成的库文件是a.out

  1. (可选)将libtestJNI.so拷贝到库路径下,如/usr/lib64
  2. 运行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
面:编程技术

你可能感兴趣的:(JNI的快速入门实践)