通过JNI实现Java对C/C++的调用

JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

大致步骤

  1. 编写带有native声明的方法的java类

  2. 使用javac命令编译所编写的java类

  3. 使用javah命令生成扩展名为h的头文件

  4. 使用C/C++实现本地方法

  5. 将C/C++编写的文件生成动态连接库

1) 编写java程序:

public class HelloNative{
  public native void greeting();//所有native所修饰的都是本地方法
 
  static{System.loadLibrary("HelloNative");//载入本地库
  }
 
  public static void main(String[] args){new HelloNative().greeting();//    System.out.println(System.getProperty("java.library.path"));
  }}

声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明该方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。 Load动态库:System.loadLibrary(“HelloNative”);加载动态库(我们可以这样理解:我们的方法 greeting()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“HelloNative”是动态库的名字。

2) 编译

javac HelloNative.java

3) 生成扩展名为h的头文件

javah HelloNative

命令执行后会在当前目录下生产一个c的头文件,名字为HelloNative.h。内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloNative */
 
#ifndef _Included_HelloNative#define _Included_HelloNative#ifdef __cplusplusextern "C" {#endif/* * Class:     HelloNative * Method:    greeting * Signature: ()V */
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jobject);
 
#ifdef __cplusplus}#endif#endif

这个h文件相当于我们在java里面的接口,这里声明了一个 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致

4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。

#include <stdio.h>#include <jni.h>#include "HelloNative.h"
 
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv * env, jobject obj){
  printf("Hello, Native!\n");}

5) 生成动态库

gcc -fPIC -I/home/elton/jdk/include -I/home/elton/jdk/include/linux -shared -o libHelloNative.so HelloNative.c

注意,必须告知编译器jni.h所在的接口位置。linux的动态库都是以lib开头,以.so结尾的,要遵守这个命名规范。-fPIC是告诉编译器生成跟位置无关的动态链接库

命令执行后,会在当前目录生成一个libHelloNative.so的动态链接库文件

6) 运行程序

java -Djava.library.path=. HelloNative

必须指定java.library.path变量的内容,告诉java你的动态链接库的位置。

或者在命令行上输入

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

这样就不用每次调试的时候都输入-Djava.library.path=.这个参数了。

当你部署的时候,你通过System.out.println(System.getProperty(“java.library.path”));得到你系统的java.library.path位置,然后把你的动态链接库拷贝到这个目录中。我用的是ubuntu 11.04 64位版本,得到的结果是

/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

这样你的动态链接库就永远都会被java访问到了,不用每次指定环境变量了。

觉得文章有用?立即:和朋友一起 共学习 共进步!

建议继续学习:

  1. Java技术路线    (阅读:5810)
  2. Java应用运维    (阅读:2993)
  3. Java陷阱(2010版)    (阅读:2648)
  4. Java将Object对象转换为String的总结合集    (阅读:2447)
  5. Java 常量值修改后不起作用    (阅读:2144)
  6. Eclipse Xtend对Java说:我帮你瘦身    (阅读:2062)
  7. Java的那些事儿    (阅读:2063)
  8. Java泛型简明教程    (阅读:1988)
  9. 如何在Hadoop集群运行jni程序    (阅读:1965)
  10. 五四陈透过PHP看JAVA系列:strtotime    (阅读:1728)

QQ技术交流群:445447336,欢迎加入!

扫一扫订阅我的微信号:IT技术博客大学习

我来评几句
登录后评论

已发表评论数()

相关站点

热门文章