Java 平台有个用户和本地 C 代码进行交互操作的 API,成为 Java Native Interface (JNI)
java是跨平台的语言,既然是跨了平台,所付出的代价就是牺牲一些对底层的控制,而java要实现对底层的控制,就要一些其他语言的帮助,这个就是native的作用了
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
大概流程:
1、在Java中声明native()方法,然后编译;
2、用javah产生一个.h文件;
3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
4、将第三步的.cpp文件编译成动态链接库文件;
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
JAVA本地方法适用的情况
1.为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2.为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3.为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
package cn.lacknb.test.jni;
/**
* <h2> </h2>
*
* @author: gitsilence
* @description:
* @date: 2022/9/24 09:02
**/
public class HelloNative {
static {
System.loadLibrary("libHelloNative");
}
public static native void sayHello();
public static void main(String[] args) {
sayHello();
}
}
这里创建的类有包名,当前就处于cn.lcknb.test.jni 的目录下
编译
javac -d ../../../../ HelloNative.java
导出头文件
到 main/java 目录下,执行
javah cn.lacknb.test.jni.HelloNative
然后会生成文件 cn_lacknb_test_jni_HelloNative.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include </Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/include/jni.h>
/* Header for class cn_lacknb_test_jni_HelloNative */
#ifndef _Included_cn_lacknb_test_jni_HelloNative
#define _Included_cn_lacknb_test_jni_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_lacknb_test_jni_HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_cn_lacknb_test_jni_HelloNative_sayHello
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
这里的 jni.h
我改成了绝对路径,具体目录在 $JAVA_HOME/include
,但是 jni.h 引用了 jni_md.h ,这个文件macOS 系统下是在 $JAVA_HOME/inclde/darwin
HelloNative.c
#include "cn_lacknb_test_jni_HelloNative.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_cn_lacknb_test_jni_HelloNative_sayHello() {
printf("Hello JNI ...");
return;
}
动态库名字必须为libxxxx.dylib(xxxx=文件名)
不同的操作系统的操作链接库的后缀是不一样的。
window:.dll
linux:.so
macOS: .dylib
编译命令:
clang -c HelloNative.c
生成动态链接库
clang -shared HelloNative.o -o libHelloNative.dylib
$JAVA_HOME/jre/lib/
Hello JNI ...