好吧,开始我的第一个JNI试验小程序

HelloWorld.java 代码清单

  1. public class HelloWorld {
  2.  
  3. static {
  4. System.loadLibrary("HelloWorld");
  5. }
  6.  
  7. public static native void hello(String msg);
  8.  
  9. public static void main(String args[]){
  10. HelloWorld hw = new HelloWorld();
  11. hw.Display();
  12. }
  13.  
  14. void Display(){
  15. System.out.println("hello,world");
  16. }
  17.  
  18. }

记得文件名必须和类名一致,编译

  javac HelloWorld

利用 javah 命令生成c 的头文件,命令形式 javah  <packagename>.<classname>,因为我没有定义包名,所以直接是类名:

  javah HelloWorld

这样在目录下将会生成以包名为文件名的头文件 HelloWorld.h

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class HelloWorld */
  4.  
  5. #ifndef _Included_HelloWorld
  6. #define _Included_HelloWorld
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*
  11. * Class: HelloWorld
  12. * Method: hello
  13. * Signature: (Ljava/lang/String;)V
  14. */
  15. JNIEXPORT void JNICALL Java_HelloWorld_hello
  16. (JNIEnv *, jclass, jstring);
  17.  
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #endif

下面我们需要建立HeloWorld的动态共享库,先创建一个HelloWorld.c, 然后将头文件中的函数定义拷贝过来,并且指定参数的变量名

  1. #include "HelloWorld.h"
  2.  
  3. JNIEXPORT void JNICALL Java_HelloWorld_hello(JNIEnv * env, jclass jz, jstring s)
  4. {
  5. }

这是个毫无用处的函数,在java程序中我们也只有声明,没有调用,现在我只是试验他是否能正常装载。用 gcc 命令进行编译:

  gcc -I/usr/lib/jdk1.6.0_45/include -I/usr/lib/jdk1.6.0_45/include/linux -fPIC  -c HelloWorld.c

gcc的 -I 选项指定头文件的搜索路径,jni.h 在jdk 的include子目录里,而jni_md.h在 include/linux下,所以要把这两个路径加入头文件的搜索路径。-c 选项指定生成 .o 文件,如果缺少 -c 选项gcc会自动链接生成可执行文件,因为在我们的程序中缺少 main 函数,所以会出现错误。另外我们希望生成的是动态链接库,所以我们不需要生成可执行文件,只要生成目标文件即可。经过执行上面的命令,在目录下会生成 HelloWorld.o

我们执行下面的命令生成动态链接库

gcc -shared -o libHelloWorld.so HelloWorld.o

-shared 指示生成共享库, 而 -o 可以指定生成的共享库的文件名,注意linux下共享库的命名是有讲究的,首先文件名必须由lib作为前缀,其次扩展名为.so, 而他们之间的名字应该和 System.loadLibrary调用指定的名字相符,而且大小写一致。

回头看看我们java文件中的代码片段:

  1. public class HelloWorld {
  2.  
  3. static {
  4. System.loadLibrary("HelloWorld"); // 会寻找 libHelloWorld.so 动态库
  5. }
  6.  
  7. ...
  8.  
  9. }

下一步使用java 命令运行我们的java程序:

  java HelloWorld

会报告错误:

  1. Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
  2. at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
  3. at java.lang.Runtime.loadLibrary0(Runtime.java:823)
  4. at java.lang.System.loadLibrary(System.java:1028)
  5. at HelloWorld.<clinit>(HelloWorld.java:6)
  6. Could not find the main class: HelloWorld. Program will exit.

这是因为java找不到我们的动态库。我们很奇怪的是明明动态库就在当前的目录下,而且文件的命名也符合标准,为何还找不到。这里的原因是java程序并非足够的智能,根据错误的提示可以知道我们可以通过设置 java.library.path 变量来指定库的搜索路径,好这样一来,问题就简单了,运行下面的命令,搞定:

  java -Djava.library.path=. HelloWorld

通过将java.libray.path=. 来将java.libray.path设置为当前目录。

浅试 JNI编程的更多相关文章

  1. 在 JNI 编程中避免内存泄漏

    JAVA 中的内存泄漏 JAVA 编程中的内存泄漏,从泄漏的内存位置角度可以分为两种:JVM 中 Java Heap 的内存泄漏:JVM 内存中 native memory 的内存泄漏. Java H ...

  2. NDK(22)JNI编程如何避免常见缺陷

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html 避免常见缺陷 假设您编写了一些新 JNI 代码,或者继承了别处的某些 J ...

  3. Android studio 下JNI编程实例并生成so库

    Android studio 下JNI编程实例并生成so库 因为公司需要为Android相机做美颜等图像后期处理,需要使用JNI编程,最近学了下JNI,并且在Android Studio下实现了一个小 ...

  4. JNI编程(二) —— 让C++和Java相互调用(2)

    3.getRamdomOrder() 这个方法会从backend得到一个随机的Order对象(抱歉这里“Random”拼错了),然后再调用java中相应的通知方法来通知foreground.getRa ...

  5. JNI编程(二) —— 让C++和Java相互调用(1)

    自己在外面偷偷的算了下,又有将近两个月没更新过blog了.趁着今天有兴致,来更新JNI编程的第二篇文章.在第一篇里,大概介绍了JNI的特点.用途和优劣.并且做一个最简单的JNI的例子,不过说实话那个例 ...

  6. 【转】android JNI编程 一些技巧(整理)

    原文网址:http://blog.csdn.net/linweig/article/details/5203716 本篇将介绍在JNI编程中如何传递参数和返回值. 首先要强调的是,native方法不但 ...

  7. Android中JNI编程的那些事儿(1)

    转:Android中JNI编程的那些事儿(1)http://mobile.51cto.com/android-267538.htm Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须 ...

  8. 【转】Android JNI编程—JNI基础

    原文网址:http://www.jianshu.com/p/aba734d5b5cd 最近看到了很多关于热补的开源项目——Depoxed(阿里).AnFix(阿里).DynamicAPK(携程)等,它 ...

  9. java jni 编程

    最近要学习Java JNI 编程. 我使用的是的windows系统.装了一个cygwin. 根据 <JNI 编程规范和指南>. 文件网址: http://wenku.baidu.com/v ...

随机推荐

  1. iOS UITableView 的beginUpdates和endUpdates

    在官方文档中是这样介绍beginUpdates的 Call this method if you want subsequent insertions, deletion, and selection ...

  2. 字母排列_next_permutation_字典序函数_待解决

    问题 B: 字母排列 时间限制: 1 Sec  内存限制: 64 MB提交: 19  解决: 5[提交][状态][讨论版] 题目描述 当给出一串字符时,我们逐个可以变换其字符,形成新的字符串.假如对这 ...

  3. vs 附加包含目录属性

    如果是在属性页里头添加了路径,则当程序拷贝到其他电脑上头的话,这个包含目录仍然存在,这就是与添加环境变量的区别.如果是通过添加环境变量配置的路径,则换了台电脑,这个路径就没有了,需要重新配置.

  4. Nginx 服务器安装及配置文件详解

    原文出处: Sean Chow(@SeanLoook)   欢迎分享原创到伯乐头条 Nginx 在工作中已经有好几个环境在使用了,每次都是重新去网上找博客,各种编译配置,今天自己也整理一份安装文档和 ...

  5. poj 1113:Wall(计算几何,求凸包周长)

    Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28462   Accepted: 9498 Description ...

  6. linux tricks 之 roundup.

    转载:http://stackoverflow.com/questions/1010922/question-about-round-up-macro 以下内容转载自stackoverflow关于 r ...

  7. mac上安装gradle

    首先,先download最新版本的gradle,网址如下:http://www.gradle.org/get-started然后将下载下来的zip包放在你要安装的路径上,我安装在/usr/local/ ...

  8. COOKIE和SESSION关系和区别

    一.cookie介绍 cookie 常用于识别用户.cookie 是服务器留在用户计算机中的小文件.每当相同的计算机通过浏览器请求页面时,它同时会发送 cookie.通过 PHP,您能够创建并取回 c ...

  9. 图解VS2010打包全过程(转)

    最近刚刚打包发布了用VS2010开发的一个收费系统,借此讲一讲打包过程,供大家参考. 首先打开已经完成的工程,如图: 下面开始制作安装程序包. 第一步:[文件]——[新建]——[项目]——安装项目. ...

  10. 自定义漂亮的Android SeekBar样式

    系统自带的SeekBar真是太难看了,不能容忍! 只能自己做了,先来张效果图 第1个Seekbar 背景是颜色,thumb是图片,上代码: <SeekBar android:id="@ ...