JNI学习笔记:第一个JNI程序
2018-03-19 21:10
423 查看
1. 什么是JNI?
1.1 JNI简介
1.2 JNI的角色
2. 为什么要用JNI?
2.1 JNI的作用
2.2 JNI的副作用
3. 第一个JNI程序 :A+B
3.1 开发环境
3.2 程序流程
3.3 Java代码
3.4 C++代码
4. 参考文献
1. 你可以使用JNI来实现“本地方法”(native methods),并在JAVA程序中调用它们。
2. JNI支持一个“调用接口”(invocation interface),它允许你把一个JVM嵌入到本地程序中。本地程序可以链接一个实现了JVM的本地库,然后使用“调用接口”执行JAVA语言编写的软件模块。
举个例子,我们实验室的项目中,要用到OpenCV库做视频处理和运算,实验室之前的开发都是Windows桌面端的,使用OpenCV/C++作为开发语言。但是现在要转移到Android APP开发中,如果采用OpenCV for Android进行开发,可能面临两个问题:
1. 之前做过的工作要重做,重复性建设;
2. OpenCV for Android对一些算法的支撑并没有提供很好的支撑,仅提供了C++的接口(简直是逼着你用JNI接口),如VideoCapture类中,受限于Android设备的特征,并无法直接调用摄像头和处理帧数据,只能在C++层面对视频进行解析,以及相关运算和操作。
如果使用JNI接口直接将原有的工作进行移植,那么一方面,可以代码复用,另一方面,也间接的解决了Java语言对算法支撑不足的问题,善莫大焉!
1. 程序不再跨平台。要想跨平台,必须在不同的系统环境下重新编译本地语言部分。
2. 程序不再是绝对安全的,本地代码的不当使用可能导致整个程序崩溃。
Java 8 64bit
其中,关键字
2.在cmd中使用javah命令生成对应的头文件
然后发现会多了一个Add.h文件
内容如下:
这个文件不用动,我们需要做的是写出该函数的函数实现
2. 项目属性配置
在“项目属性” –> “VC++目录” –>“包含目录”中配置JNI文件的属性,路径是你的Java安装路径+
在“项目属性” –> “常规” –> “配置类型”中选 动态库.dll
写函数体
b0e0
编译动态库,结果如下:
把dll库粘贴到Java代码的根目录下,开始运行
至此,第一个JNI程序,完成。
[2]. JNI Oracle官方参考文档
[3]. 翻译文档:JNI 编程指南
1.1 JNI简介
1.2 JNI的角色
2. 为什么要用JNI?
2.1 JNI的作用
2.2 JNI的副作用
3. 第一个JNI程序 :A+B
3.1 开发环境
3.2 程序流程
3.3 Java代码
3.4 C++代码
4. 参考文献
1. 什么是JNI?
1.1 JNI简介
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。1.2 JNI的角色
JNI可以这样与本地程序进行交互:1. 你可以使用JNI来实现“本地方法”(native methods),并在JAVA程序中调用它们。
2. JNI支持一个“调用接口”(invocation interface),它允许你把一个JVM嵌入到本地程序中。本地程序可以链接一个实现了JVM的本地库,然后使用“调用接口”执行JAVA语言编写的软件模块。
2. 为什么要用JNI?
JNI是JAVA平台的一个重要特征,使用它我们可以重用以前用C/C++写的大量代码。JNI的部分设计思想来源于Netscape的Java Runtime Interface(JRI)。使用JNI可以结合C++和Java两种语言的不同优势,使得我们的开发产品具有更强大的功能和更好的体验。2.1 JNI的作用
一方面,C++具有很好的执行效率和广泛的算法开源库,但是C++的开发成本和维护成本都过高,而另一方面,Java有更广的应用场景(Web开发、服务器开发、移动开发等),Java提供JNI接口,能够使C++代码运行在Java的环境中,使C++具有更好的应用场景,一方面能够将海量的C++开源库进行代码复用,减少了开发成本。举个例子,我们实验室的项目中,要用到OpenCV库做视频处理和运算,实验室之前的开发都是Windows桌面端的,使用OpenCV/C++作为开发语言。但是现在要转移到Android APP开发中,如果采用OpenCV for Android进行开发,可能面临两个问题:
1. 之前做过的工作要重做,重复性建设;
2. OpenCV for Android对一些算法的支撑并没有提供很好的支撑,仅提供了C++的接口(简直是逼着你用JNI接口),如VideoCapture类中,受限于Android设备的特征,并无法直接调用摄像头和处理帧数据,只能在C++层面对视频进行解析,以及相关运算和操作。
如果使用JNI接口直接将原有的工作进行移植,那么一方面,可以代码复用,另一方面,也间接的解决了Java语言对算法支撑不足的问题,善莫大焉!
2.2 JNI的副作用
请记住,一旦使用JNI,JAVA程序就丧失了JAVA平台的两个优点:1. 程序不再跨平台。要想跨平台,必须在不同的系统环境下重新编译本地语言部分。
2. 程序不再是绝对安全的,本地代码的不当使用可能导致整个程序崩溃。
3. 第一个JNI程序 :A+B
3.1 开发环境
Visual Studio 2013 UltimateJava 8 64bit
3.2 程序流程
我们用C++写一个A+B的函数,在VS中编译成dll动态链接库(Linux环境下是so库),然后在Java代码中加载该库,并传入A和B的值,在C++代码层计算并反回结果于Java层,完成一次数据传递。3.3 Java代码
1.先写Java代码,把需要的函数原型写出来,这里,我们定义C++做A+B的函数库叫做libmath,函数原型为int addByCPP(int a,int b);
import java.util.Scanner; import java.io.*; public class Add{ public native static int addByCPP(int a,int b); static{ System.loadLibrary("libmath"); } public static void main(String args[]){ int a,b; Scanner sc = new Scanner(System.in); System.out.println("At java file,input a and b:"); a = sc.nextInt(); b = sc.nextInt(); int c = addByCPP(a,b); System.out.println(); System.out.print("At java file:a+b=" + c); } }
其中,关键字
native定义了所声明的函数是JNI函数,
System.loadLibrary函数加载了其所在的动态链接库
libmath。
2.在cmd中使用javah命令生成对应的头文件
然后发现会多了一个Add.h文件
内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class Add */ #ifndef _Included_Add #define _Included_Add #ifdef __cplusplus extern "C" { #endif /* * Class: Add * Method: addByCPP * Signature: (II)I */ JNIEXPORT jint JNICALL Java_Add_addByCPP (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif
这个文件不用动,我们需要做的是写出该函数的函数实现
3.4 C++代码
1. 在VS2013中创建空项目,注意项目名字最好是libmath,对应上一步的库名。2. 项目属性配置
在“项目属性” –> “VC++目录” –>“包含目录”中配置JNI文件的属性,路径是你的Java安装路径+
\Java\jdk1.8.0_31\include`
在“项目属性” –> “常规” –> “配置类型”中选 动态库.dll
写函数体
#include"Add.h" #include<jni.h> #include<iostream> using namespace std; JNIEXPORT jint JNICALL Java_Add_addByCPP (JNIEnv *, jclass, jint a, jint b){ cout << "At cpp file: a = " << a << " b = " << b << endl; cout << "a+b = " << a + b; return (a + b); }
b0e0
编译动态库,结果如下:
把dll库粘贴到Java代码的根目录下,开始运行
至此,第一个JNI程序,完成。
4. 参考文献
[1]. 百度百科,“JNI”词条[2]. JNI Oracle官方参考文档
[3]. 翻译文档:JNI 编程指南
相关文章推荐
- JNI学习笔记(一)第一个JNI详细例子配图文
- 【Android】第一个JNI测试程序
- Android studio下jni的配置和第一个helloword程序
- JNI第一个程序
- NDK-JNI实战教程(一) 在Android Studio运行第一个NDK程序
- JNI学习笔记(一)第一个JNI详细例子配图文
- NDK-JNI实战教程(一) 在Android Studio运行第一个NDK程序
- Android NDK编程,我的第一个hello-jni程序,如何调用自己编译的so库
- Android studio配置jni以及第一个jni程序
- 我的第一个Linux下的JNI程序
- Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序
- AndroidStudio上的第一个jni程序——NDK入门
- win7第一个JNI程序(我是菜鸟)
- Android JNI编程(七)——使用AndroidStudio编写第一个JNI程序
- Android JNI编程(七)——使用AndroidStudio编写第一个JNI程序
- 第一个JNI程序
- Android JNI 开发 第一个程序
- Android第一个JNI程序
- 第一个JNI程序
- NDK-JNI实战教程(一) 在Android Studio运行第一个NDK程序