1.JNI是什么?

JNI(Java Native Interface) Java本地接口,又叫Java原生接口。它允许Java调用C/C++的代码,同时也允许在C/C++中调用Java的代码。

可以把JNI理解为一个桥梁,连接Java和底层。其实根据字面意思,JNI就是一个介于Java层和Native层的接口,而Native层就是C/C++层面。

2.为什么要用JNI?

  1. 能够重复使用一些现成的、具有相同功能的的C/C++代码
  2. 因为C/C++是偏向底层的语言,所以使用C/C++能够更加的高效,而且也使得Java能够访问操作系统中一些底层的特性。

3.怎么使用JNI?

完整的示例源码托管在 Github

  1. 使用Java声明native方法
// com/maxzuo/jni/StringUtils.java
public class StringUtils { public static native String getRandStr(int length);
}
  1. 使用javac编译StringUtils.java成StringUtils.class
// 在src/main/java目录下执行
javac com/maxzuo/jni/StringUtils.java
  1. 使用上面生成的class文件生成头文件用于编写C/C++代码的头文件:
// 在src/main/java目录下执行
javah -jni com.maxzuo.jni.StringUtils // 执行完命令后,生成了com_maxzuo_jni_StringUtils.h文件
  1. 用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对象
  1. 生成动态库文件
// 将生成的头文件放在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。

  1. 使用生成的动态库文件
// 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

Java基础-JNI入门示例的更多相关文章

  1. Java基础语法入门01

    Java基础语法入门01 学习java你要先进行去了解JDK,JRE,JVM JDK Java开发工具包 JRE Java语言开发的运行环境 JVM Java虚拟机,用于Java语言的跨平台所用. 当 ...

  2. java基础知识入门

    一.java简介及原理图 Java的前世今生 Java之父詹姆斯·高斯林: 1967年, 12岁用报废的电话机和电视做了一台电子游戏机; 1983年, 获得卡内基梅隆大学计算机科学博士学位; 1983 ...

  3. Java基础之入门

    写写基础,顺便回顾下,再深层次思考下哪些深入的没弄明白. Java是Sun Microsystems于1995年推出的高级编程语言  其版本 由 1.1 -> 1.2 -> 1.3 -&g ...

  4. Java基础之入门介绍

    基础知识 1.JVM.JRE和JDK的区别:     JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性.                   java ...

  5. Java基础(入门Java)

    今天是学习Java的第一天,为了保证在暑假里持续高效的学习,决定每周写一篇博客汇报总结当周进度,以此来督促自己不断的向更深更远的方向迈进.Java刚刚入门,看到的人若觉得某些地方不妥欢迎进行批评指导, ...

  6. 二十二、Java基础--------GUI入门

    在java学习过程中GUI是一个比较特殊的知识体系(笔者对安卓不是很了解),似乎在为安卓的学习做着准备,本文将将展示一个综合案例. 创建一个类似于记事本的程序,包含打开与保存功能. package G ...

  7. Java基础语法入门

    一.Java运行原理 写好java代码,执行javac命令,通过jvm把.java源文件编译成.class文件,执行java命令把字节码文件编译成特定平台能识别的机器码 二.标识符 1.标识符是用于数 ...

  8. [java 基础]反射入门

    原文 概况 使用java的反射,可以让我们检查(或者修改)类,接口,字段,方法的特性.当你在编译期不知道他们的名字的时候非常有用. 除此之外,可以使用反射来创建实例,调用方法或者get/set 字段值 ...

  9. Java基础 while 简单示例

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

随机推荐

  1. CF390A Inna and Alarm Clock 题解

    Content 平面内有 \(n\) 个整点 \((x_i,y_i)\).每次可以去掉一行或一列的点,问最少去几次(按行去点或按列去点二者只能选择一种). 数据范围:\(1\leqslant n\le ...

  2. 七层LB-NGINX 客户端获取协议Proxy Protocol介绍

    协议诞生背景 在Web分布式系统中,一般会搭建复杂的load blance系统来提供高性能的web服务. 7层的SLB 有基于nginx/淘宝变种tengine的.后端RS会无法获取真实客户端IP. ...

  3. C++ 11新特性:std::future & std::shared_future) (转载)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  4. Vim使用简介

    Vim操作 Vim真的很酷:D 编辑模式 正常模式:在文件中四处移动光标进行修改 插入模式:插入文本 替换模式:替换文本 可视化(一般,行,块)模式:选中文本块 命令模式:用于执行命令 在不同的操作模 ...

  5. JAVA微信公众号网页开发——生成自定义微信菜单(携带参数)

    官网接口地址:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.ht ...

  6. Linux(centos)使用shell脚本停止启动jar包

    在jar包目录下创建一个文件,后缀为 .sh #!/bin/bash # stop service pid=`ps -ef | grep "jar包名字" | grep -v &q ...

  7. JAVA发送邮件报错,返回500 Error: bad syntax问题

    把项目部署在Linux系统的centos服务器,发送邮件报错了. 500 Error: bad syntax 处理办法 [root@master bin]# hostname master 显示 ma ...

  8. C++封装C语言读写文件

    自己项目需要,封装C语言读写文件. 为了兼容低版本的编译器,因为低版本的编译器(比如,Vs2010,Vs2008)他们可能不支持 modern c++. 项目 使用 cmake管理的项目. 可以在 g ...

  9. windows串口之虚拟串口和Access port

    关于 本文将介绍自己常用的串口工具,演示环境为Windows. 1. 虚拟串口 1.1 没有那么多的物理串口, 用虚拟串口来凑.需要软件Configure Virtual Serial Port Dr ...

  10. Adversarial Examples Are Not Bugs, They Are Features

    目录 概 主要内容 符号说明及部分定义 可用特征 稳定可用特征 可用不稳定特征 标准(standard)训练 稳定(robust)训练 分离出稳定数据 分离出不稳定数据 随机选取 选取依赖于 比较重要 ...