JNI的使用
JAVA基础知识
Package机制
功能:
- 把功能相似或相关的类或接口组织在同一个包中 --- 集中管理类。
- 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,
不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,
应该加上包名加以区别 --- 避免类名冲突 - 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类 --- 权限
例子:
创建com.test包
package com.test
public class A implements B{
public void testA(){
}
}
编译流程
java源代码(符合语言规范)-->javac-->.class(二进制文件)-->jvm-->机器语言(不同平台不同种类)
Javac、Javah和Java
Javac: 编译命令,将Java源文件编译成.class字节码文件。
-encoding 指定源文件的文件编码格式
Javah: 生成实现本地方法所需的C头文件和源文件。
Java: 运行字节码文件,由JVM对字节码进行解释和运行。
JNI(Java Native Interface)使用流程
- 创建JAVA文件Algorithm.java,并创建包和接口类,接口声明为native,如public native int GetA();
- 使用Javah工具生成C头文件 com_alg_Algorithm.h,命令"javah com.alg.Algorithm";
- 根据C头文件实现C代码Algorithm.cpp,并生成.so(linux)或.dll(windows)动态库文件;
- Java代码LoadLibrary加载动态库,调用native代码,命令"javac test.java"。
代码示例:Algorithm.java-步骤一
package com.alg;
public class Algorithm
{
public native int GetA();
public native int GetB();
}
代码示例com_alg_Algorithm.h-步骤二
JNIEXPORT jint JNICALL Java_com_alg_Algorithm_GetA();
JNIEXPORT jint JNICALL Java_com_alg_Algorithm_GetB();
代码示例algorithm.cpp-步骤三
#include"com_alg_Algorithm.h"
//"jni.h"在安装JDK目录include中可以得到
#include"jni.h"
#include<iostream>
JNIEXPORT jint JNICALL Java_com_alg_Algorithm_GetA()
{
std::cout << "Hello World A!" << std::endl;
return 0;
}
JNIEXPORT jint JNICALL Java_com_alg_Algorithm_GetA()
{
std::cout << "Hello World B!" << std::endl;
return 0;
}
代码示例test.java-步骤四
import com.alg.Algorithm;
import java.io.IOException;
import java.io.InputStream;
public class Test
{
static
{
System.loadLibrary("Algorithm");
}
public static void main(String[] args) throws IOException
{
Algorithm alg = new Algorithm();
alg.GetA();
alg.GetB();
}
}
特别注意点
javah生成的头文件中函数的命名,是根据java类Algorithm存在的路径来名,以下述接口名为例:
jint JNICALL Java_com_alg_Algorithm_GetA()
对应java存在的路径为:app\src\main\java\com\alg\Algorithm。
也就是说若javah生成的接口名与调用接口的java文件路径不一致时会导致接口无法正常被调用。
JNA(Java Native Access)
需求: 很少有java程序员愿意编写调用.dll/.so库中原生函数的java程序。
解决: 它提供一组java工具类用于在运行期间动态访问系统本地共享类库,
java开发人员只要在一个java接口中描述目标native library的函数与结构,
JNA将自动实现Java接口到native function的映射,而不需要编写任何Native/JNI代码,
大大降低了Java调用本体共享库的开发难度。