JNI入门学习笔记(测试环境:ubuntu gcc 4.4.5)
来源:互联网 发布:阿里云 自建数据库 编辑:程序博客网 时间:2024/05/16 04:33
参考文章:
http://blog.csdn.net/yuleslie/article/details/7056577
java native specification 官方文档。
深入理解android:卷1
我这里尝试写一个在ubuntu上直接运行的java调用jni程序,通过这个慢慢入门,然后提高吧。
1. 编辑一个java文件HelloJNI.java(名字随意),这个java文件会去调用jni的方法。
class HelloWorld{private native void print();public static void main(String[] args){new HelloWorld().print();}static{System.loadLibrary("MyJNI");}}
不需要任何头文件包含。代码中看到有个main函数,另外main函数会调用native的print方法。
System.loadLibrary("MyJNI")是要我们要加载的JNI库,实际加载过程中会找这个拓展后的文件名,Linux下为libMyJNI.so,windows下为MyJNI.dll
接下来我们需要去建立我们的MyJNI库,并要保证我们调用native的print函数时能正常调用到JNI库中对应的XXX_print函数,所谓“注册JNI函数”。
2. 编写注册JNI函数
为保证我们JNI库中的函数与java中调用的print对应,我们需要完成JNI函数的注册,相当与映射的意思吧。
这里我们先测试使用简单的静态注册方法,为省去要按JNI规范手动编写代码的困难,我们使用javah来生成头文件。
先将上面的HelloJNI.java用javac编译成 .class文件
tongjiang@tongjiang-laptop:/home/workdir/source/test$ javac HelloJNI.java
此时目录下会根据你HelloJNI.java中定义的HelloWorld类生成一个文件:HelloWorld.class
我们此时使用javah来生成.h文件
tongjiang@tongjiang-laptop:/home/workdir/source/test$ javah HelloWorld
这样会生成HelloWorld.h 头文件,内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class: HelloWorld * Method: print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
我们如果自己手动coding的话就要按JNI规范来写,JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject)
我们在jni库中要编写的print函数的原型就是这样了,print被扩展为Java_HelloWorld_print,
静态注册时虚拟机会按这种扩展方法来找jni函数。
另外还有搞怪的,如果我们java文件中print函数是写成有下划线的,假如是print_me,
扩展时需要写成JNIEXPORT void JNICALL Java_HelloWorld_print_lme(JNIEnv *env, jobject)
注意me前面的那个l,另外如果print函数有传参进来时,JNI对应的函数原型的参数需要按JNI的数据类型进行转换,这个是后话。
3. 我们按.h文件的函数原型来写native的c++代码:hello.cpp
#include <jni.h>#include <stdio.h>#include "HelloWorld.h"JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj){printf("Hello, i am Native\n");return ;}
单纯打印一句话: Hello, i am Native
我们来编译一下这个cpp文件
tongjiang@tongjiang-laptop:/home/workdir/source/test$ g++ -shared -I '/home/tongjiang/Program/jdk1.6.0_25/include' -I'/home/tongjiang/Program/jdk1.6.0_25/include/linux' '/home/workdir/source/test/hello.cpp' -o libMyJNI.so
-shared会把cpp编译成动态库
-o 输出的目标文件,我们这里是动态库libMyJNI.so
-I 是include头文件的目录 jni.h在jdk1.6.0_25/include'中,而jni.h又包含的头文件在jdk1.6.0_25/include/linux中.
4. 我们可以去尝试java调用jni了
我们运行java HelloWorld
tongjiang@tongjiang-laptop:/home/workdir/source/test$ java HelloWorldException in thread "main" java.lang.UnsatisfiedLinkError: no MyJNI in java.library.pathat java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)at java.lang.Runtime.loadLibrary0(Runtime.java:823)at java.lang.System.loadLibrary(System.java:1028)at HelloWorld.<clinit>(HelloJNI.java:10)Could not find the main class: HelloWorld. Program will exit.
提示找不到这个库no MyJNI in java.library.path,因为System.loadLibrary会到系统库中找对应的so,但我们的so没有放到系统的lib目录中。
我们这里可以配置export LD_LIBRARY_PATH=/home/workdir/source/test
这样的话会链接LD_LIBRARY_PATH这个目录下的对应so
再次运行java HelloWorld
tongjiang@tongjiang-laptop:/home/workdir/source/test$ java HelloWorld
Hello, i am Native
也可以不export LD_LIBRARY_PATH
执行下面的命令也ok
tongjiang@tongjiang-laptop:/home/workdir/source/test$ java -Djava.library.path=./ HelloWorld
Hello, i am Native
好,现在我们基本通路已经打通了,java能通过jni调用native层的的函数,我们再尝试函数中传递参数和native调用java层的方法。
- JNI入门学习笔记(测试环境:ubuntu gcc 4.4.5)
- JNI入门学习笔记
- JNI入门学习笔记
- android JNI入门-学习笔记
- Ubuntu下Android JNI初步学习之——搭建相关环境和测试Demo
- jni入门学习笔记(一)
- jni入门学习笔记(二)
- jni入门学习笔记(一)
- jni入门学习笔记(一)
- JNI 入门学习笔记(一)
- NDK开发学习笔记—JNI入门
- [linux学习笔记] GCC环境安装问题
- Linux学习笔记 gcc入门02
- ubuntu android JNI 入门
- ubuntu 环境 cmake 学习笔记
- Ubuntu下gcc入门
- (笔记)Ubuntu下安装arm-linux-gcc-4.4.3.tar.gz (交叉编译环境)
- (笔记)Ubuntu下安装arm-linux-gcc-4.4.3.tar.gz (交叉编译环境)
- 为何我设计的ListView看上去不同?
- shell history log file
- android 2.* 下如何使用actionbar
- jquery 熟悉框架开发
- jquery实现全选全不选反选以及遍历取值
- JNI入门学习笔记(测试环境:ubuntu gcc 4.4.5)
- JAVA设计模式 —行为模式总结
- 【framework】EventLog分析
- 多线程共享对象之volatile关键字
- linux服务器性能收集
- CSS HACK : IE6 FF google 等浏览器 hack方法收集
- POJ 1087 A Plug for UNIX(最大二分匹配)
- android中listview滑动变黑的解决办法
- linux图形界面编程基本知识