使用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. mysql_事务

    事务是针对数据的,不是针对结构的 存储引擎innodb支持事务,myisam不支持事务需求:有一张银行账户表,有A用户给B账户转账,A账户减少,B账户增加,但是A操作之后断电. 解决方案:A减少钱,但 ...

  2. Dinic算法——重述

        赛前赛后算是第三次接触Dinic算法了,每一次接触都能有种很好的感觉,直男的我没法描述~~ 已经比较懂得DInic的基本算法思想了 首先是bfs进行进行分层处理,然后dfs寻找分层后的最大流, ...

  3. 调用azkaban接口,upload 本地zip文件

    使用azkaban部署任务,可以将job文件打成zip包,通过web页面上传. 如图 但是当我们实践CI持续化部署的时候,要实现自动的部署上线. 这时就要调用azkaban提供的api. 地址如下:h ...

  4. 深入探讨 Java 类加载器(转)

    原帖地址:https://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要 ...

  5. CentOS6.5分区与文件系统

    1 分区介绍 inux分区不同于windows,linux下硬盘设备名为(IDE硬盘为hdx(x为从a—d)因为IDE硬盘最多四个,SCSI,SATA,USB硬盘为sdx(x为a—z)),硬盘主分区最 ...

  6. 最全面的Git 使用规范装逼指南[转载]

    <!DOCTYPE html> <script type="text/javascript"> window.logs = { pagetime: {} } ...

  7. SQL Server 阻塞原因分析

    这里通过连接在sysprocesses里字段值的组合来分析阻塞源头,可以把阻塞分为以下5种常见的类型(见表).waittype,open_tran,status,都是sysprocesses里的值,“ ...

  8. 新建WebAPI项目时遇到的问题

    1   处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错误模块“ManagedPipelineHandler” 以管理员运行下面的命令注册 ...

  9. 03_python_基本数据类型

    一.基本数据类型 整数 bool 字符串: 可以保存少量数据并进行相应的操作 列表 list: 存大量数据 [] 元组 tuple: 不可改变的() 字典 dict: 保存键值对,一样可以存储大量的数 ...

  10. redis常用命令(一)

    一.redis常见的数据操作命令 http://redisdoc.com/ 二.键(key) keys *: 查询所有的key. exists key:判断某个key是否存在. move key db ...