使用JNI调用本地代码,整个开发流程主要包括以下几个步骤:
1、创建一个Java类(IntArray.java);
2、使用javac编译该类(生成IntArray.class);
3、使用javah -jni 产生头文件(生成IntArray.h);
4、使用本地代码实现头文件中定义的方法(编写IntArray.c);
5、编译生成本地动态库(生成libIntArray.so);
6、使用Java运行程序。

创建Java类:IntArray.java

class IntArray {
private native int sumArray(int[] arr);
public static void main(String[] args) {
IntArray p = new IntArray();
int arr[] = new int[10];
for(int i = 0; i < 10; i++) {
arr[i] = i;
}
int sum = p.sumArray(arr);
System.out.println("Sum = " + sum);
}
static {
System.loadLibrary("IntArray");
}
}

注:
     1、在Java代码中声明本地方法必须有"native"标识符,native修饰的方法,在Java代码中只作为声明存在。例如: private native int sumArray(int[] arr);
     2、在调用本地方法前,必须首先装载含有该方法的本地库. 如IntArray.java中所示,置于static块中,在Java VM初始化一个类时,首先执行这部分代码,这可保证调用本地方法前,装载了本地库。

static {
  System.loadLibrary("IntArray");
 }

二、使用javac编译该类(生成IntArray.class)
javac IntArray.java
三、使用javah -jni 产生头文件(生成IntArray.h)
javah -jni IntArray

生成的 IntArray.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class IntArray */ #ifndef _Included_IntArray
#define _Included_IntArray
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: IntArray
* Method: sumArray
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_IntArray_sumArray
(JNIEnv *, jobject, jintArray); #ifdef __cplusplus
}
#endif
#endif

四、使用本地代码实现头文件中定义的方法(编写IntArray.c)
复制IntArray.h成IntArray.c,对于IntArray.c做以下修改:
1、添加头文件:#include "IntArray.h"
2、去掉以下几句
#ifndef _Included_IntArray
#define _Included_IntArray
#endif
3、实现头文件中定义的方法:

IntArray.c

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include "IntArray.h"
/* Header for class IntArray */ #ifdef __cplusplus
extern "C" {
#endif
/*
* Class: IntArray
* Method: sumArray
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_IntArray_sumArray
(JNIEnv *env, jobject obj, jintArray arr)
{
jint buf[] = {};
jint i = , sum = ;
(*env)->GetIntArrayRegion(env, arr, , , buf);
for(i = ; i < ; i++)
{
sum += buf[i];
}
return sum;
}
#ifdef __cplusplus
}
#endif

五、编译生成本地动态库(生成libIntArray.so)
根据本地代码(IntArray.h,IntArray.c)生成本地动态库,命令如下:

gcc -I /home/oracle/jdk1..0_05/include -I /home/oracle/jdk1..0_05/include/linux/ -fPIC -shared -o libIntArray.so IntArray.c

其中 -I后面是java的include文件夹地址,请根据您具体的java版本以及安装路径作相应改变;
-f后面的PIC表示生成的库中符号是与位置无关的(PIC就是Position Independent Code),关于PIC,可以参考这篇文章
http://www.gentoo.org/proj/en/hardened/pic-guide.xml

-shared表示共享,共享库后缀名.so可以认为是shared object的简称;
-o libIntArray.so,可以理解为编译后输出libIntArray.so库。

六、使用Java运行程序
java IntArray

可能出现以下结果:

java IntArray

Exception in thread "main" java.lang.UnsatisfiedLinkError: no IntArray 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 IntArray.<clinit>(IntArray.java:15)

分析异常提示可知,我们之前生成的共享库不在系统默认的共享库路径中,程序找不到共享库报错。
解决方法有两个:
1、临时指定共享库libIntArray.so的路径。
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH  注:该方法只在当前会话窗口有效,切换到另外一个终端窗口,则需要重新指定共享库路径。也可直接在环境变量中加入:LD_LIBRARY_PATH=.:$ORACLE_HOME/lib:/usr/lib64:/usr/lib:/usr/local/lib64:/usr/local/lib  命令行中使用:source ~/.bash_profile  使当前增加的环境变量生效

2、运行时加上参数指定共享库libIntArray.so的路径。
java -Djava.library.path=.  IntArray 注:-D:设置Java平台的系统属性。 此时JavaVM可以在当前位置找到该库。

通过以上任意方法,您都可以得到正确的运行结果:
java IntArray
Sum = 45

--------------------------------------------

文章来源于:http://www.2cto.com/os/201108/101048.html

CentOS Java C JNI的更多相关文章

  1. JAVA使用JNI调用C++动态链接库

    JAVA使用JNI调用C++动态链接库 使用JNI连接DLL动态链接库,并调用其中的函数 首先 C++中写好相关函数,文件名为test.cpp,使用g++编译为DLL文件,指令如下: g++ -sha ...

  2. 【Java的JNI快速学习教程】

    1. JNI简介 JNI是Java Native Interface的英文缩写,意为Java本地接口. 问题来源:由于Java编写底层的应用较难实现,在一些实时性要求非常高的部分Java较难胜任(实时 ...

  3. java通过jni方式获取硬盘序列号(windows,linux)

    linux系统java通过jni方式获取硬盘序列号 http://blog.csdn.net/starter110/article/details/8186788 使用jni在windows下读取硬盘 ...

  4. JAVA中JNI的简单使用

    了解JNI:JAVA因其跨平台特性而受人们喜爱,也正因此,使得它和本机各种内部联系变得很少,所以JNI(Java Native Interface)就是用来解决JAVA本地操作的一种方式.JAVA通过 ...

  5. Java通过JNI调用C/C++

    From:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与 ...

  6. java通过JNI接口调用C语言-初级

    JNI(java native interface):即java本地调用C的接口. 先看整体运行: 下面是过程: #vim test.java public class test{ public na ...

  7. Java通过JNI调用dll详细过程(转)

    源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无 ...

  8. centos java环境搭建

    我个人配置的是阿里云centos 7.4 64bit 不存在openjdk 看下面内容的情况下看是否存在openjdk java -version 如果返回java版本值,则存在openjdk,需要卸 ...

  9. Java之JNI的介绍与应用20170622

    /*************************************************************************************************** ...

随机推荐

  1. protobuf和protostuff的区别

    在我们的开发过程中,序列化是经常需要处理的问题,比如在做分布式访问数据时,或者是在做redis缓存存储数据时,如果我们涉及的知识面不够广的话,可能会简单的使用JDK的序列化,也即在需要序列化的类上im ...

  2. utf8.php

    <?php /** * */ class Utf8 { function __construct() { global $CFG; if( preg_match('/./u', '') === ...

  3. bootstrap3文章

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta name= ...

  4. mysql命令行客户端结果分页浏览

    转载请注明出处:http://xiezhenye.com/2008/06/mysql%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%ae%a2%e6%88%b7%e7%ab%af%e7% ...

  5. node.js second day

    create global link 使用全局模式安装的包不能直接通过require使用,但是nmp提供了一个 nmp link ,这个可以打破限制 $ nmp link [express] ./no ...

  6. 数据库常见索引解析(B树,B-树,B+树,B*树,位图索引,Hash索引)

    B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...

  7. Linux Shell脚本编程基础(11)

    实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程 ...

  8. pika配置文件说明

    # Pika 端口 port : 9221 # pika进程数量,不建议超过核心数量,pika是多线程的 thread-num : 1 # Sync 线程数量 sync-thread-num : 6 ...

  9. Android MediaPlayer setDataSource failed

    今天在尝试使用MediaPlayer播放音乐时出了一个问题,在使用 mp.setDataSource(this,Uri.parse("/sdcard/Music/adele.mp3" ...

  10. iframe 自适应高度和宽度

    <iframe src="pay/index.aspx" marginheight="0" marginwidth="0" frame ...