JNI/NDK develop guide(1)
来源:互联网 发布:java final修饰数组 编辑:程序博客网 时间:2024/05/27 14:15
JNI/NDK develop guide(1)
JNI全称是Java Native Interface(Java本地接口)单词首字母的缩写,本地接口就是指用C和C++开发的接口。由于JNI是JVM规范中的一部份,因此可以将我们写的JNI程序在任何实现了JNI规范的Java虚拟机中运行。同时,这个特性使我们可以复用以前用C/C++写的大量代码。
开发JNI程序会受到系统环境的限制,因为用C/C++语言写出来的代码或模块,编译过程当中要依赖当前操作系统环境所提供的一些库函数,并和本地库链接在一起。而且编译后生成的二进制代码只能在本地操作系统环境下运行,因为不同的操作系统环境,有自己的本地库和CPU指令集,而且各个平台对标准C/C++的规范和标准库函数实现方式也有所区别。这就造成使用了JNI接口的JAVA程序,不再像以前那样自由的跨平台。如果要实现跨平台,就必须将本地代码在不同的操作系统平台下编译出相应的动态库。
JNI开发流程主要分为以下6步:
1、编写声明了native方法的Java类
2、将Java源代码编译成class字节码文件
3、用javah -jni命令生成.h头文件(==javah是jdk自带的一个命令,-jni参数表示将class中用native声明的函数生成jni规则的函数==)
4、用本地代码实现.h头文件中的函数
5、将本地代码编译成动态库(windows:.dll,linux/unix:.so,mac os x:*.jnilib)
6、拷贝动态库至 java.library.path 本地库搜索目录下,并运行Java程序
通过上面的介绍,相信大家对JNI及开发流程有了一个整体的认识,下面通过一个HelloWorld的示例,再深入了解JNI开发的各个环节及注意事项。
1: we create a HelloWorld.java original file
public class HelloWorld { public static native String sayHello(String name); // 1.this is to create a native method public static void main(String[] args) { String text = sayHello("yangxin"); // 3.call native method System.out.println(text); } static { // 2.Load to achieve the dynamic library of native function, only need to write the name of the dynamic libraries System.loadLibrary("HelloWorld"); } }
2: step use javac command make.java original file to .class bytecode file
注意:HelloWorld放在com.study.jnilearn包下面
javac src/com/study/jnilearn/HelloWorld.java -d ./bin
-d 表示将编译后的class文件放到指定的目录下,这里我把它放到和src同级的bin目录下
默认生成的.h头文件名为:com_study_jnilearn_HelloWorld.h(包名+类名.h),也可以通过-o参数指定生成头文件名称:
javah -jni -classpath ./bin -o HelloWorld.h com.study.jnilearn.HelloWorld
参数说明:
-classpath :类搜索路径,这里表示从当前的bin目录下查找
-d :将生成的头文件放到当前的jni目录下
-o : 指定生成的头文件名称,默认以类全路径名生成(包名+类名.h)
==注意:-d和-o只能使用其中一个参数==
3:Use native method to implementation .h file’s function com_study_jnilearn_HelloWorld.h
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_study_jnilearn_HelloWorld */#ifndef _Included_com_study_jnilearn_HelloWorld #define _Included_com_study_jnilearn_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: com_study_jnilearn_HelloWorld * Method: sayHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif
This is the code of HellowWorld.c
// HelloWorld.c #include "com_study_jnilearn_HelloWorld.h" #ifdef __cplusplus extern "C" { #endif /* * Class: com_study_jnilearn_HelloWorld * Method: sayHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello( JNIEnv *env, jclass cls, jstring j_str) { const char *c_str = NULL; char buff[128] = { 0 }; c_str = (*env)->GetStringUTFChars(env, j_str, NULL); if (c_str == NULL) { printf("out of memory.\n"); return NULL; } printf("Java Str:%s\n", c_str); sprintf(buff, "hello %s", c_str); (*env)->ReleaseStringUTFChars(env, j_str, c_str); return (*env)->NewStringUTF(env, buff); } #ifdef __cplusplus } #endif
一般在类的静态(static)代码块中加载动态库最合适,因为在创建类的实例时,类会被ClassLoader先加载到虚拟机,随后立马调用类的static静态代码块。这时再去调用native方法就万无一失了。加载动态库的两种方式:
System.loadLibrary("HelloWorld"); System.load("/Users/yangxin/Desktop/libHelloWorld.jnilib");
方式1:只需要指定动态库的名字即可,不需要加lib前缀,也不要加.so、.dll和.jnilib后缀
方式2:指定动态库的绝对路径名,需要加上前缀和后缀
如果使用方式1,java会去java.library.path系统属性指定的目录下查找动态库文件,如果没有找到会抛出java.lang.UnsatisfiedLinkError异常
Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld2 in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860) at java.lang.Runtime.loadLibrary0(Runtime.java:845) at java.lang.System.loadLibrary(System.java:1084) at com.study.jnilearn.HelloWorld.<clinit>(HelloWorld.java:13)
有两种方式可以让java从java.library.path找到动态链接库文件,聪明的你应该已经想到了。
方式1:将动态链接库拷贝到java.library.path目录下
方式2:给jvm添加“-Djava.library.path=动态链接库搜索目录”参数,指定系统属性java.library.path的值
java -Djava.library.path=/Users/yangxin/Desktop
Linux/Unix环境下可以通过设置LD_LIBRARY_PATH环境变量,指定库的搜索目录。
- JNI/NDK develop guide(1)
- JNI/NDK develop guide(2) How JVM find native method
- NDK/JNI Develop Guide (4) How to use Array
- NDK/JNI Develop guide(6) access the instance variables and static variables
- NI/NDK Develop Guide (3) Handle String
- Android JNI Develop 1 setup
- Android JNI 开发 Demo by NDK (native develop kit)
- Symbol Develop Guide
- NDK/Jni Develop Guild(5)c/c++ access Java Method and static method
- android ndk jni 实例1
- JNI/NDK开发指南(1)
- Android NDK(JNI)开发
- JNI NDK开发(一)
- Android Ndk(Beginner ‘s guide)(1.2)
- Android Ndk(Beginner ‘s guide)(1.3)
- Android Ndk(Beginner ‘s guide)(2.1)
- Android Ndk(Beginner ‘s guide)(2.2)
- Android Ndk(Beginner ‘s guide)(2.3)
- 如何在Android studio项目中查看R.java文件
- windows7 update更新失败,还原更改 解决办法
- android 文件保存数据
- PowerDesigner使用教程|使用方法
- ADB Android 调试利器之常用ADB指令分享
- JNI/NDK develop guide(1)
- GMap.Net开发之技巧小结
- Think PHP(TP)框架的基本使用 (三)
- Ajax技术讲解
- 再按一次退出程序
- iOS:应用沉睡之时 后台传输服务
- 网络解析xml
- # 输入框的抖动效果
- Pull解析xml文件时工具类的代码