史上最详细的JNI入门教程HelloNative
为什么80%的码农都做不了架构师?>>>
欢迎点击「算法与编程之美」↑关注我们!
本文首发于微信公众号:"算法与编程之美",欢迎关注。
1 为什么写本文
互联网上已经有很多介绍 JNI 的入门教程,为什么还要多此一举写本文呢?
相信大家在平时阅读一些教程类文章时都遇到过这样的情况,按照教程描述的步骤一步步的来操作,结果却并没有得到教程期望的结果。遇到各种各样的问题,最后解决不了这些问题,进而放弃,放弃的原因很简单那就是对于一个未知的领域,读者遇到问题后无法自己解决,而所阅读的教程类文章并没有对这一问题进行详细的描述,导致最后选择了放弃。
通过分析我们发现,大多的教程类文章都有一个共同的问题,就是重步骤而忽视读者在阅读过程中可能遇到的问题的分析。
我们期望改变这一现状,对于教程类文章,我们不仅介绍具体的操作步骤,而且更重要的是介绍读者在进行操作时可能遇到的一些关键问题,并对这些问题进行详细分析,从而帮助您彻底的解决问题。
2 HelloNative教程
下面将介绍编写 JNI 入门教程HelloNative程序的编写。
主要的步骤为:
1) 编写 HelloNative.java 程序;
2) 编译并得到 HelloNative.h 头文件;
3) 编写 HelloNative.c 程序;
4) 编译动态链接库libHelloNative.jnilib;
5) 运行HelloNative程序。
先从整体上了解一下我们需要做的事情有哪些,接下来我将介绍在mac 系统下每一个步骤的详细内容并标注难点。
2.1 编写 HelloNative.java 程序
public class HelloNative{static{System.loadLibrary("HelloNative"); //难点一}public static native void sayHello();public static void main(String[]args){new HelloNative().sayHello();}}
2.2 编译并得到 HelloNative.h 头文件
执行如下命令:
javac HelloNative.javajavah HelloNative
2.3 编写 HelloNative.c 程序
#include <stdio.h>#include "HelloNative.h"JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *env, jclass jc) //难点二{printf("Hello Native\n");}
2.4 编译动态链接库libHelloNative.jnilib
//难点三
gcc HelloNative.c -o libHelloNative.jnilib -dynamiclib
-I/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/
-I/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/darwin/
2. 5 运行HelloNative程序
java HelloNative
3 难点分析
虽然上面介绍的是mac 系统下程序的编写,读者的系统可能大多是windows,但是不影响大家的编写。
接下来将对第2节中标记的三个难点进行分析,这三个难点也是大家遇到的最多的问题。
难点一
JNI存在的意义就在于能够让 Java 程序和 C/C++等其他编程语言之间能够非常方便的交互,通过JNI 我们就能够非常方便的做到这一点。
有些同学可能会问为什么要这样做?所有的任务我都用 Java 来做不是更好吗,为什么一会用 Java 一会用C/C++,这样多语言岂不是更麻烦吗。
这个问题其实有多方面的原因,以下将列举几点原因:
- Java语言是运行在 JVM 之上的,因此对JVM 依赖的非常高。众所周知,这样的机制使得 Java 语言相对其他C 语言来说效率变得低下,因此一些对执行效率要求较高的任务我们可以用 C 语言来编写,然后上面的程序可以通过JNI 来调用 C 编写的模块。
- 假设你的项目组是一个多语言的组,存在着 Java、Ruby、Python 等多种编程语言的人员,如何让这些人员编程的程序能够相关调用呢?
那么 Java 是如何做到这一点的呢?
将其他语言编写的模块编译成动态库,然后在Java程序中加载这个动态库,进而使用该库。
System.loadLibrary("HelloNative"); //难点一
因此大家看到的这行代码就是 Java 程序加载编译后的动态库HelloNative。这里面大家需要注意的是HelloNative 并不是最终动态库的全称,不同的操作系统下这个动态库的名称是不一样的,如:
Windows 下叫*.dll
Linux 下叫*.so
Mac 下叫*.jnilib
大家都知道 Java 是跨平台的程序,因此在Java 代码里面肯定不能指定某一种平台具体的动态库完整名称,因此只是给出了这个动态库的名称而非全称。
对于本例我们最终在不同平台下生成的动态库全称是:
Windows HelloNative.dllLinux libHelloNative.soMac libHelloNative.jnilib
这个知识点非常有用,难点3中会再次涉及,请大家务必提前掌握。
难点二
这个函数的定义大家可能会写错,而且大家通常情况下不能完全按照教程来写。
如果大家写过 c/c++ 语言的程序应该都知道,在c/c++中,一个程序分为头文件 hello.h 和其实现文件hello.c,其中在头文件中定义了函数声明,而在实现文件中对函数进行实现。
在了解这个知识点以后,我们就知道 HelloNative.c 文件中应该如何突破难点2了。
打开 HelloNative.h 文件,找到对应的函数声明。
JNIEXPORT void JNICALL Java_HelloNative_sayHello (JNIEnv *, jclass);
函数声明大家应该都能看懂,本例中大家需要注意的是,在形参的声明中可以不指定形参的名称,而只是给出形参的类型。因此本例中的JNIEnv* 和jclass都是形参的类型。
所以难点二中大家看到的代码是下面这样,其中env和jc是具体的形参名称。
JNIEXPORTvoid JNICALL Java_HelloNative_sayHello(JNIEnv *env, jclass jc) //难点二
难点三
这个难点也是大家遇到的最多问题的地方,需要重点阐述。
如何编译一个C 语言的动态库?
大家都知道 C 语言一个非常著名的编译器叫gcc,因此本文介绍如何用 gcc 来编译动态库。(这里面大家需要注意的是 gcc 只是c语言编译器其中的一种,除了 gcc 还有很多其他的编译器如微软等公司出品的。)
不同的操作系统下编译动态库的命令也是不一样的,如:
Windows下:gcc -shared HelloNative.c -o HelloNative.dllLinux 下:gcc -shared HelloNative.c -o libHelloNative.soMac 下:gcc -dynamiclib HelloNative.c -o libHelloNative.jnilib
在难点一中我们给大家阐述了不同的系统中动态库的名称是不一样的,本节就有所体现。
其次,我们还需要给出gcc编译动态库中jni.h和jni_md.h两个头文件的路径。
因此,我们接下来要找到这两个头文件所在的目录,你可以通过各种各样的文件搜索工具(如 windows 下的强大的搜索神器everything)找到他们。在 Linux 和Mac 下面我们可以通过下面的命令快速找到:
locate jni.h>/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/jni.hlocate jni_md.h>/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/darwin/jni_md.h
注意,我们只需要两个文件所在的目录:
/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/
/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/darwin/
准备工作做好了,最后我们加上这个头文件的路径就大功告成了。
Mac 下:
gcc -dynamiclib HelloNative.c -o libHelloNative.jnilib-I/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/-I/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include/darwin/
注意:
- -I中的I为大写;
- -I/Library中的I与/Library之间没有空格。
此处我们只给出 mac 下的路径,其他系统类似。
4 总结
本文介绍了 JNI 的入门教程HelloNative程序的编写,相对于其他的教程,我们更加重视大家在实际学习过程中的一些难点,通过对三个难点的分析,相信大家能够更好的掌握相关的知识点。
如您对此种教程类文章感兴趣,欢迎持续关注“算法与编程之美”微信公众号,了解更多此类文章。
转载于:https://my.oschina.net/gschen/blog/1613890
史上最详细的JNI入门教程HelloNative相关推荐
- Eclipse安装教程 ——史上最详细安装Java Python教程说明
Eclipse安装教程 --史上最详细安装Java&Python教程说明 ...
- 史上最简单的Git入门教程
1. 版本控制系统简介 1.1 何为版本控制 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变,文件的版本号都将增加.除了记录版 ...
- 史上最全Python快速入门教程,让你快速入门python学好python
Python是面向对象,高级语言,解释,动态和多用途编程语言.Python易于学习,而且功能强大,功能多样的脚本语言使其对应用程序开发具有吸引力. Python的语法和动态类型具有其解释性质,使其成为 ...
- agx 安装ros opencv_史上最全的OpenCV入门教程!这篇够你学习半个月了!万字长文入门...
一.Python OpenCV 入门 欢迎阅读系列教程,内容涵盖 OpenCV,它是一个图像和视频处理库,包含 C ++,C,Python 和 Java 的绑定. OpenCV 用于各种图像和视频分析 ...
- 史上最全的OpenCV入门教程!这篇够你学习半个月了!万字长文入门
推荐下我自己建的人工智能Python学习群:[809160367],群里有我整理的一份关于pytorch.python基础,图像处理opencv\自然语言处理.机器学习.数学基础等资源库,想学习人工智 ...
- 史上最详细宝塔面板安装教程(收藏)
下面稍微介绍一下如何使用阿里云服务器安装宝塔面板. 概述 如果还有不了解宝塔面板怎么使用的小伙伴,可以看下我总结的系列教程,保证从新手变老鸟: [建站流程科普] 个人和企业搭建网站基本流程及六个主要步 ...
- 魔方教程一步一步图解(史上最简单的魔方入门教程)新手一看就会
IT数学系列最常见的魔方是三阶魔方,是匈牙利布达佩斯建筑学院厄尔诺·鲁比克教授在1974年发明的.魔方教程一步一步图解新手一看就会. 魔方教程一步一步图解 魔方共6色6面,每面又分为中央块(最中间的块 ...
- 【Python教程】史上最全Python快速入门教程,满满都是干货
Python是面向对象,高级语言,解释,动态和多用途编程语言.Python易于学习,而且功能强大,功能多样的脚本语言使其对应用程序开发具有吸引力. Python的语法和动态类型具有其解释性质,使其成为 ...
- 史上最详细的Vmware安装教程(一)-创建Linux虚拟机
本文将演示如何使用Vwmare workstation软件创建Linux虚拟机,通过学习,我们将可以按照自己下需求,来创建一个安装Linux操作系统(Centos)的虚拟机,虚拟机的CPU.硬盘.网卡 ...
最新文章
- jQuery 基础选择器/层级选择器/隐式迭代
- 使用AndroidStudio创建自定义gradle插件并被引用实战例子
- 什么时候会触发这个策略呢?
- TEG《选择》乘风破浪 · 披荆斩棘
- 安兔兔2019年1月安卓手机排行榜发布:小米无愧性价比之王
- 剑指offer之使数组的奇数在偶数前面
- 如何将列表分成大小均匀的块?
- 用于登录的mysql语句_mysql常用语句
- Navicat Premium相关注册码
- 12-搜索前端开发-按分类搜索
- 计算机安装系统作用是什么,告诉你重装系统对电脑有什么影响
- 【CV】FPN:用于目标检测的特征金字塔网络
- 室内环境下的3D 目标检测调研
- io多路复用的原理和实现_IO多路复用机制详解
- 响应式分布式区别_边缘计算的七种定义,边缘计算与云计算、雾计算的区别
- MYSQL数据库的数据存储文件
- 高校公寓管理系统的设计与实现
- Xilinx FPGA开发板 Digilent Spartan-3E 学习资料整理
- 鼠标爱心的html代码,网页js代码鼠标点击爱心特效(富强、自由、爱国、敬业、友善)...
- VRTK4开发VR2:射线
热门文章
- python怎么定义一个变量为空列表_python – 为什么一个类变量没有在列表理解中定义,但另一个是?...
- mybaitis快速生成_Mybatis中使用mybatis-generator结合Ant脚本快速自动生成Model、Mapper等文件...
- ssm框架逻辑删除mysql_ssm框架小总结——批量删除
- ble l2cap 工作过程_BLE 链路层报文详解
- c++和java哪个难_为什么说C语言比Java难?
- HTML怎么把文字分栏_html代码怎样优化更利于SEO排名
- dhcp服务器设置无线,无线网dhcp服务器设置
- java ztree json_java 树形转换JSON 工具类 / 树形子父级菜单递归 JSON 格式
- jquery控制span的display属性为 none
- 项目中SQL语句的一些应用总结