您的位置:首页 > 编程语言 > Java开发

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

2018-03-01 19:02 260 查看
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) 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java  JNI Mac vim gcc