Java很好地封装了硬件,最大可能地规避了不同硬件平台的硬件处理,让程序员能专注于软件。但是“寄人篱下哪能不弯腰”?当然这么说有一些情绪化,Java与C/C++相比有一个无法避开的劣势——效率!C算是离硬件最近的高级语言,特别是在嵌入式应用领域,C可以直接操作内存,直面硬件而执行。对于小型移动设备而言具有无法拒绝的优跃性。
于是常在岸上走的Java,在这种情况下不得不下水。JNI便出现了,它在Java与C/C++之间提供了一个本地库的调用接口,使得Java与不同语言间可以相互沟通协作。
工作准备:
1、Linux:本文测试环境为Ubuntu12.04LTS,其他Ubuntu版本或Linux应该也能实现。当然,Windows与Mac也是可以的,只是操作上略有不同。
2、JDK1.8_131:用于编译执行Java程序,其他版本的JDK也可以。
3、gcc:用于将C或C++程序编译成动态或静态库。
本文默认已准备好环境。
一、编写Java程序,MyJni.java
public class MyJni { static{ System.load("/home/smallfish/workspace/Java/libmyjni.so"); } public native void display(); public native double sum(double x, double y); public static void main(String[] args) { MyJni myJni = new MyJni(); System.out.print(myJni.sum(1,1)); System.out.print("\n"); myJni.display(); } }
1、在Java类中只需要声明native方法 ,这两个方法的实现是在libmyjni.so中,所以需要加载此库,使用System.load("库文件的绝对路径")。
2、使用javah生成本地方法头文件,MyJni.h
# javah MyJni
javah会自动生成MyJni.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class MyJni */ #ifndef _Included_MyJni #define _Included_MyJni #ifdef __cplusplus extern "C" { #endif /* * Class: MyJni * Method: display * Signature: ()V */ JNIEXPORT void JNICALL Java_MyJni_display (JNIEnv *, jobject); /* * Class: MyJni * Method: sum * Signature: (DD)D */ JNIEXPORT jdouble JNICALL Java_MyJni_sum (JNIEnv *, jobject, jdouble, jdouble); #ifdef __cplusplus } #endif #endif
二、用C语言实现native方法MyJni.c
#include "jni.h" #include "MyJni.h" #include <stdio.h> JNIEXPORT void JNICALL Java_MyJni_display(JNIEnv *env, jobject obj){ env = env; obj = obj; printf("Hello, JNI!\n"); } JNIEXPORT jdouble JNICALL Java_MyJni_sum(JNIEnv *env, jobject obj, jdouble a, jdouble b){ env = env; obj = obj; return a+b; }
注意:
1、jni.h是Java提供的头文件,它在JDK的"安装目录/include"目录下
2、jni_md.h在JDK“安装目录/include/linux”目录下。
为了编译方便于是乎将这两个文件与MyJni.c文件放在一起,所以使用“#include "jni.h" ”。
三、将C实现编译成动态链接库
# gcc -fPIC -c MyJni.c # gcc -fPIC -shared MyJni.o -o libmyjni.so
生成库文件后将此文件放至Java程序加载库的路径下。
四、编译Java文件
#javac MyJni.java
五、执行
转载请注明:OpenMind » Java JNI初体验