Linux下java使用JNI调用C++
1.JNI介绍
JNI即Java Native Interface(Java本地接口),是一个协议,主要作用为:实现Java调用c/c++代码(类库),或者C/C++调用Java代码
2.准备JNI
先用javah,根据.java文件生成.h头文件,然后用C++实现这个接口
2.1先在目录下创建JNI.java文件
内容如下
//JNI.java文件
public class JNI{
//创建一个native接口方法,此方法在C++代码中实现
public native int doSomething();
//静态代码块,加载由C++代码生成的.dll动态链接文件(.dll相当于Java中的jar包吧...)
static{
System.loadLibrary("JNIDLL");
}
}
2.2使用javac编译JNI.java生成JNI.class,然后使用javah编译JNI.class得到JNI.h文件,步骤如下
- javac编译
javac JNI.java - javah编译JNI.class(不用带后缀名)
javah JNI - 打开JNI.h查看
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNI */
#ifndef _Included_JNI
#define _Included_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNI
* Method: doSomething
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_JNI_doSomething
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
2.3编写C++代码(JNIDLL.cpp)实现JNI.java中的doSomething()方法(native修饰)
注意方法名是JNI.h中的Java_JNI_doSomething
//JNIdll.cpp文件
#include<stdio.h>
#include<jni.h>
#include "JNI.h"
JNIEXPORT jint JNICALL Java_JNI_doSomething
(JNIEnv *, jobject){
//实现代码
int i = 777;
printf("in doSomething \n");
return i;
}
2.4使用g++编译器生成.so动态库文件
命令如下:
我的jdk路径和你们的不一样,使用的时候要修改一下
g++ -I /java_android/jdk1.8.0_131/include -I /java_android/jdk1.8.0_131/include/linux/ -fPIC -shared -o libJNIDLL.so JNIDLL.cpp
也可以将jni.h和jni_md.h拷贝到当前目录下,然后编译:
两个文件在jdk1.8.0_131/include和jdk1.8.0_131/include/linux/下
g++ -fPIC -shared -o libJNIDLL.so JNIDLL.cpp
3.使用JNI
在java主程序中调用上面准备好的JNI文件
3.1 编写主程序HelloWorld.java文件
//HelloWorld.java文件
import java.lang.Thread;
import java.util.Scanner;
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
//创建JNI的对象call
JNI jni = new JNI();
int count =1;
while (true)
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//调用call()方法;
int i = jni.doSomething();
System.out.println("第 " + count + " 次 sleep 2s ");
count++;
}
}
}
3.2编译和运行
- 编译
javac HelloWorld.java - 运行
java HelloWorld
4.完整过程
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r-- 1 tsh tsh 534 Mar 29 17:03 HelloWorld.java
-rw-rw-r-- 1 tsh tsh 229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r-- 1 tsh tsh 309 Apr 1 11:14 JNI.java
virtual-machine:~/codeTest/javaTest$ javac JNI.java
virtual-machine:~/codeTest/javaTest$ javah JNI
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r-- 1 tsh tsh 534 Mar 29 17:03 HelloWorld.java
-rw-rw-r-- 1 tsh tsh 349 Apr 1 14:43 JNI.class
-rw-rw-r-- 1 tsh tsh 229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r-- 1 tsh tsh 354 Apr 1 14:44 JNI.h
-rw-rw-r-- 1 tsh tsh 309 Apr 1 11:14 JNI.java
virtual-machine:~/codeTest/javaTest$ g++ -I /java_android/jdk1.8.0_131/include -I /java_android/jdk1.8.0_131/include/linux/ -fPIC -shared -o libJNIDLL.so JNIDLL.cpp
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r-- 1 tsh tsh 534 Mar 29 17:03 HelloWorld.java
-rw-rw-r-- 1 tsh tsh 349 Apr 1 14:43 JNI.class
-rw-rw-r-- 1 tsh tsh 229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r-- 1 tsh tsh 354 Apr 1 14:44 JNI.h
-rw-rw-r-- 1 tsh tsh 309 Apr 1 11:14 JNI.java
-rwxrwxr-x 1 tsh tsh 8136 Apr 1 14:46 libJNIDLL.so*
virtual-machine:~/codeTest/javaTest$ javac HelloWorld.java
virtual-machine:~/codeTest/javaTest$ ll
-rw-rw-r-- 1 tsh tsh 955 Apr 1 14:46 HelloWorld.class
-rw-rw-r-- 1 tsh tsh 534 Mar 29 17:03 HelloWorld.java
-rw-rw-r-- 1 tsh tsh 349 Apr 1 14:43 JNI.class
-rw-rw-r-- 1 tsh tsh 229 Mar 29 17:07 JNIDLL.cpp
-rw-rw-r-- 1 tsh tsh 354 Apr 1 14:44 JNI.h
-rw-rw-r-- 1 tsh tsh 309 Apr 1 11:14 JNI.java
-rwxrwxr-x 1 tsh tsh 8136 Apr 1 14:46 libJNIDLL.so*
virtual-machine:~/codeTest/javaTest$ java HelloWorld
Hello World
in doSomething
第 1 次 sleep 2s
in doSomething
第 2 次 sleep 2s
in doSomething
第 3 次 sleep 2s