Java基础-JNI入门示例
1.JNI是什么?
JNI(Java Native Interface) Java本地接口,又叫Java原生接口。它允许Java调用C/C++的代码,同时也允许在C/C++中调用Java的代码。
可以把JNI理解为一个桥梁,连接Java和底层。其实根据字面意思,JNI就是一个介于Java层和Native层的接口,而Native层就是C/C++层面。
2.为什么要用JNI?
- 能够重复使用一些现成的、具有相同功能的的C/C++代码
- 因为C/C++是偏向底层的语言,所以使用C/C++能够更加的高效,而且也使得Java能够访问操作系统中一些底层的特性。
3.怎么使用JNI?
完整的示例源码托管在 Github
- 使用Java声明native方法
// com/maxzuo/jni/StringUtils.java
public class StringUtils {
public static native String getRandStr(int length);
}
- 使用javac编译StringUtils.java成StringUtils.class
// 在src/main/java目录下执行
javac com/maxzuo/jni/StringUtils.java
- 使用上面生成的class文件生成头文件用于编写C/C++代码的头文件:
// 在src/main/java目录下执行
javah -jni com.maxzuo.jni.StringUtils
// 执行完命令后,生成了com_maxzuo_jni_StringUtils.h文件
- 用C语言来实现函数
#include "com_maxzuo_jni_StringUtils.h"
JNIEXPORT jstring JNICALL Java_com_maxzuo_jni_StringUtils_getRandStr(JNIEnv *env,jobject obj, int length){
...
}
其中:
将java的native方法转换成C函数声明的规则是这样的:Java_{package_and_classname}_{function_name}(JNI arguments),包名中的点换成单下划线。
参数介绍:
- JNIEnv *:这是一个指向JNI运行环境的指针,后面我们会看到,我们通过这个指针访问JNI函数
- jobject:这里指代java中的this对象
- 生成动态库文件
// 将生成的头文件放在native目录, 在native目录下执行如下命令:
gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/include -I /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/include/darwin StringUtils.c -o libStringUtils.jnilib
注意在不同的操作系统,能够生成的动态库文件也是不一样的,在Windows中,要生成.dll文件,在Linux中要生成.so文件,在Mac OS X中要生成.jnilib文件。
同时定义生成的库文件名的时候也要遵循:lib+文件名+扩展名的原则。本例中我们在Mac OS X中所以我们定义生成的库文件为:libStringUtils.jnilib。
- 使用生成的动态库文件
// com/maxzuo/jni/Main.java
public class Main {
static {
System.load("/xxx/java-native-interface/native/libStringUtils.jnilib");
}
public static void main(String[] args) {
String randStr = StringUtils.getRandStr(4);
System.out.println("call StringUtils.getRandStr str = " + randStr);
}
}
其中,运行时加载本地库, JDK提供了两个方法:
System.loadLibrary(String libname) 加载由libname参数指定的系统,参数为库文件名,不包含库文件的扩展名;会自动加载依赖。
譬如libA.so和libB.so有依赖关系,虚拟机在载入libA.so的时候会先去java.library.path下查找libB.so。System.load(String filename):参数为库文件的绝对路径且带文件后缀;不会自动加载依赖。同等场景下,不会自动加载依赖。
补充:
1)通过JVM启动参数指定:-Djava.library.path=/path
2)通过设置环境变量指定:export LD_LIBRARY_PATH=/path
最新文章
- 终于解决:升级至.NET 4.6.1后VS2015生成WCF客户端代理类的问题
- Testing - 质量保证与质量控制
- Java中的10颗语法糖
- 转:DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)之一
- serialVersionUID作用
- Codeforces 148D Bag of mice 概率dp(水
- 第二天0605下午——超链接<;a>;与图片<;img>;
- 解决Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/Student_recruit]]
- QTcpSocket 相关知识总结
- Scrum的3种角色划分--2048小游戏
- [转] web前端js构造无法销毁的类UUID识别码,识别浏览器设备唯一性
- Android开发 ---ORMLite实现数据的增删改查,单例模式,Dao栈
- 一个使用Jmeter做接口性能测试的实战案例
- [译]CQRS介绍
- idea中使用thymeleaf标签时有红色的波浪线怎么去掉
- ubuntu直接删除文件而不是移动到回收站
- 【struts2】自定义拦截器
- freemarker逻辑判断写法#if
- Unity3d ugui 实现image代码换图
- Java入门:注册模块的实现
热门文章
- freeswitch APR-UTIL库消息队列实现
- CF1076B Divisor Subtraction 题解
- libevent源码学习(10):min_heap数据结构解析
- vue+uniapp实现美颜拍照录像,相册选择 | 录像限制时长,美颜拍照录像
- IPtables 之“四表五链”
- Spring Boot应用程序启动器
- 分享一下java需要的一些技术
- 【LeetCode】787. Cheapest Flights Within K Stops 解题报告(Python)
- codeforce 597C-Subsequences(dp+树状数组)
- 第四十九个知识点:描述在IPsec和TLS后的基本想法