Java JNI 的本意是Java Native Interface (Java 本地接口),它是为了方便Java 调用C和

C++等本地代码所封装的一层接口。

我们都知道,Java 的优点是跨平台,但是作为优点的同时,其在和本地交互的时候就出现了短板。Java 的跨平台特性导致其本地交互的能力不够强大,一些和操作系统相关的特性Java 无法完成,于是Java 提供了JNI专门用于和本地代码交互,这样就增强了Java 语言的本地交互能力。通过Java JNI,用户可以调用用C、C++所编写的本地代码。

NDK 则是Android 所提供的一个工具集合,通过NDK 可以在Android 中更加方便地通过JNI 来访问本地代码,比如C 或者C++。NDK 还提供了交叉编译器,开发人员只需要简单地修改mk 文件就可以生成特定CPU平台的动态库。

使用NDK 有如下好处:

(1) 提高代码的安全性。由于SO 库反编译比较困难,因此NDK 提高了Android 程序

的安全性。

(2) 可以很方便地使用目前已有的C/C++开源库。

(3) 便于平台间的移植。通过C/C++实现的动态库可以很方便地在其他平台上使用。

(4) 提高程序在某些特定情形下的执行效率,但是并不能明显提升Android 程序的

性能。

介绍完了基本概念,下面先来实现本章内容,java工程的JNI基本调用,一共分五步。

1、在java文件中中声明native方法,以及要加载的动态库

System.loadLibrary("jni-test");//加载动态库模块

而动态库的全名是

注意:“.”后面的是动态库的存储格式,在不同系统下都是不一样的,

windows下是.dll,linux下是.so,mac下是.jnilib。

动态库名称都以“lib”开头,而代码中声明加载的库名时,不用加“lib”。

两个native方法get和set,格式如上。

2、编译该java文件,并单独生成头文件

javac JniTest.java命令是编译文件,并生成class文件。

java JniTest。是是用javah命令对class文件生成头文件,就是JniTest.h。

JniTest.h的内容有注释是不可编辑的,但是这里面的很多内容之后都要用到,内容如下:

这里面有JNi的语法,比如两个函数方法get和set,函数名遵守的规则的是Java_包名_类名_方法名(虽然我偷懒java文件没有包名)。这个规则有印象就好,不用记,因为这些靠javah命令就能自动生成。

解释几个关键词

JNIEXPORT 和JNIEXPORT:是jni.h中定义的宏;

JNIEnv*:表示指向JNI环境的指针,可以用来访问JNI提供的接口方法;

jobject:表示java 对象中的this;

String:  JNI中的类型,对应着java中的string

3、在c或c++文件中,实现JniTest.h中的两个方法,如下:

可以看见,test.c文件中的这两个方法的方法名和参数类型,是直接从之前的JniTest.h中复制过来的,我们给参数类型后面添加了参数名,并实现了内部的方法。

Jobject 用thiz不用this,是因为在java中this有特殊含义,如果在ide中,编译整个工程的话,后果严重你懂的。

#include"JniTest.h",包含了之前的java头文件(test.c和该头文件最好放同一目录下)。

几个JNI的接口方法定义如下:

(官方文档链接)

https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#wp9502

jstring  NewStringUTF(JNIEnv *env, const char *bytes);//将string转为jstring类型

const  jbyte* GetStringUTFChars(JNIEnv *env, jstring string,

jboolean*isCopy);//以utf格式返回一个数组指针

void  ReleaseStringUTFChars(JNIEnv *env, jstring string,

constchar *utf);//释放指针资源

4、通过gcc编译c或c++文件(我的例子是c),生成动态库(我的系统是mac,注意生成动态库后缀格式)如下:

-shares  -fPIC ,是生成动态库

-I  /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include,是我的jdk路径

test.c,是c代码文件

-o libjni-test.jnilib,是编译要生成的文件名和格式(windows下是.dll,linux下是.so,mac下是.jnilib)

**********************************************补充说明***************************************

因为新换了台mac,用的是原生的mac的jdk,编译时会报错,信息如下:

//Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/include/jni.h:45:10: fatal error: 'jni_md.h' file not found
#include "jni_md.h"^
1 error generated.

第一个解决的办法是添加一个 -I jdk路径/darwin 参数:

首先,简化jdk路径,用别名代替
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home

其次,在“4、”中的原命令基础上,添加-I jdk路径/darwin 参数

gcc -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -fPIC test.c -o libjni-test.jnilib

这条命令中用别名JAVA_HOME简化了jdk路径,但是跟“4、”中原命令相比,只是多了个-I jdk路径/darwin 参数

第二个解决办法自然是去官网,重新下载jdk 安装,具体流程不做细讲。安装完成后可使用“4、”中的命令

**********************************************补充结束***************************************

5、指定动态库路径,执行java的class文件如下:

ls命令,可见动态库文件libjni-test.jnilib在当前目录

Java  JniTest是执行已编译好的class文件

-Djava.library.path=. 指定了动态库所在目录,即当前目录,执行结果感人。

我在当前目录再建一个jni目录,并在jni目录下单独放一个动态库libjni-test.jnilib。

我再次执行的时候,-Djava.library.path=jni,修改了动态库的路径位置,结果同样感人。

完成

动态库文件在生成之后就是独立的模块,放在哪里都没问题,要修改相关功能,也只需要单独修改该模块,非常方便。

demo的源码链接如下:

https://github.com/wu2007369/-java-jni

JNI和NKD入门系列一,纯java工程下JNI的开发流程(mac系统)相关推荐

  1. JNI和NKD入门系列二,mac环境下配置NDk,并在android studio上进行JNI开发

    1.下载并配置NDK NDK各版本下载地址在此http://blog.csdn.net/shuzfan/article/details/52690554,对应好各自系统.(压缩文件记得解压) 接下来将 ...

  2. JNI和NKD入门系列三,在android studio上设置javah和ndk-build的快捷键

    1.首先点开偏好设置 2.点开External Tools并点击添加按钮 3.出来这样的页面,重要的是Insert macro按钮 4.类似的,选择一个内置变量并确定insert 5.会出现一个头尾由 ...

  3. sqlcipher java_纯java环境下sqlsqlcipher解密sqlite数据库文件

    由于工作需要,最近一周以来研究sqlite数据库文件的解密方法.最终采用sqlcipher工具进行解密.由于sqlcipher的实现大多是支持android的,修改为纯java平台下的代码有难度,因此 ...

  4. java word - 2:POI开发流程

    接上文,本章介绍下POI的开发流程 不同于Freemarker那样将模板和数据分离的方式,POI是没有模板的,模板和数据是糅合在一起的. POI的开发流程其实网上教程都比较多了,我这边就将我写好的工具 ...

  5. ZYNQ系列(五) ZYNQ下的驱动开发

    ZYNQ系列(五) ZYNQ下的驱动开发 第一章 Petalinux创建工程 第二章 Petalinux-config配置说明 第三章 QSPI自启动工程 第四章 将文件打包进文件系统 第五章 将文件 ...

  6. 【JAVA零基础入门系列】Day2 Java集成开发环境IDEA

    [JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day ...

  7. 【JAVA零基础入门系列】Day14 Java对象的克隆

    [JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day ...

  8. Java极速入门系列:第一章Java概述、Java环境、IDEA开发工具

    Java极速入门-第一章Java概述.Java环境.IDEA开发工具 一.什么是Java 1.好的编程语言的特性 2.Java的特点 3.Java的运行机制 4.Java的三大体系 5.Java环境 ...

  9. mac电脑配置java环境变量_教你在Mac系统中配置JAVA环境变量的方法

    Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征.下面向大家介绍Mac电脑上如何配置Java ...

最新文章

  1. 使用Google App Engine、Google Closure Library与Clojure编写HTML5应用
  2. 一文带你了解Java的命名规范!
  3. 优酷电视剧爬虫代码实现一:下载解析视频网站页面(3)补充知识点:htmlcleaner使用案例...
  4. 【QGIS入门实战精品教程】5.1:QGIS地理坐标转火星坐标系(GCJ02)案例教程
  5. 2016第三届科学数据大会——科学数据与创新发展
  6. C盘的“压缩驱动器以节约磁盘空间”有用吗
  7. 笔记︱信用风险模型(申请评分、行为评分)与数据准备(违约期限、WOE转化)
  8. iphone移动端踩坑
  9. linux网络子系统分析(二)—— 协议栈分层框架的建立
  10. [Cogs728] [网络流24题#3] 最小路径覆盖 [网络流,最大流,二分图匹配]
  11. 解决 ERROR oslo_service.periodic_task AttributeError: ‘ComputeNode‘ object has no attribute ‘nodename‘
  12. python菜鸟教程mac安装_Python菜鸟教程 | 多平台安装
  13. 阅读替换净化规则_免费阅读APP-阅读下载 v3.2安卓版(免费小说阅读器纯净无广告)-KK下载站...
  14. Oracle RMAN 的 show,list,crosscheck,delete命令整理
  15. 2019蓝桥杯国赛总结
  16. android将vendor挂载为读写,挂载android只读文件系统为可读写
  17. golang图片属性orientation在image.Decode后丢失,导致图片上传后旋转
  18. HTML、XHTML和HTML5区别和概念
  19. 如何使用Logger命令将消息添加到Linux日志文件
  20. python 以lambda函数形式,实现计算x的y次方

热门文章

  1. 游戏时间 (10 分)
  2. Python小白练习之球弹跳
  3. 基于Visual Graph快速开发出电力系统
  4. STM32蓝牙小车制作全过程---刚入门的小白也能会
  5. node.js的前世今生(特色篇)
  6. 【转】Clique共识算法
  7. 车间动态调度的研究方法
  8. java中画三角形的方法_java画谢尔宾斯基三角形
  9. 算法基础:快速排序题
  10. java.util.Date、java.sql.Date和java.sql.Timestamp之间的转换