java基础之JNI原理
利用JNI实现安卓的Java代码调用C语言API。
JNI是Java Native Interface的缩写,也就是Java本地接口的意思。Java为什么需要JNI这种呢?我们知道Java是一种平台无关性的语言,平台对于上层的java代码来说是透明的,在大部分的情况下是不需要JNI的,但是我们可能遇到如下一下情况:
1.java代码需要得到一个文件的属性,但是找不到相关的API;
2.在java代码中需要用到某种算法,但是这种算法时用C实现并封装在动态链接库文件中的。
如果没有JNI,上面的问题就会变得很棘手.举个例子说明:在Android中我们想要操作串口的时候会发现当前的Android SDK并没有提供任何写串口的API,对于底层的串口操作需要使用C来完成。而Android的应用程序是基于java实现的,应用程序想要访问到串口就需要JNI技术了。
接下来通过实际的例子来说明java如何通过JNI实现C\C++的函数调用
1.开发环境介绍:主机系统为64位Ubuntu 14.04, jdk版本jdk1.8.0_45。
2.程序清单1~/jni_test/com/magc/jni/HelloWorld.java
package com.magc.jni;
public class HelloWorld
{
static
{
System.loadLibrary("Hello");
}
public native void DisplayHello();
public static void main(String[] args)
{
new HelloWorld().DisplayHello();
}
}
3.进如jni目录后,编译该java类,命令:
javac HelloWorld.java
执行后在该目录下生成 HelloWorld.class 文件
4.进入jni_test目录,使用javah命令生成头文件:
javah -jni com.magc.jni.HelloWorld
在当前目录下生成 com_magc_jni_HelloWrold.h 头文件
5.程序清单2 com_magc_jni_HelloWrold.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_magc_jni_HelloWorld */
#ifndef _Included_com_magc_jni_HelloWorld
#define _Included_com_magc_jni_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_magc_jni_HelloWorld
* Method: DisplayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
此头文件中的Java_com_magc_jni_HelloWorld_DisplayHello(JNIEnv *, jobject)方法,是将来与动态链接库交互的接口,并需要名字保持一致。
6.程序清单3 jni_HelloWroldlmpl.cpp
在jni_test目录下新建jni_HelloWroldlmpl.cpp源文件
#include <jni.h>
#include "com_magc_jni_HelloWorld.h"
#include "stdio.h"
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *, jobject)
{
printf("From jni_helloworldImpl.cpp :");
printf("Hello world !\n");
}
此C++文件实现了上述头文件中的函数,注意方法函数名要保持一致。
7.编译生成动态库libHello.so,命令:
g++ jni_helloworldImpl.cpp -o libHello.so
成功后,便会在当前目录下生成动态链接库libHello.so文件。
本人在执行这一步的过程中遇到了头文件”jni.h”和”jni_md.h”未找到的情况,这两个头文件路径伟jdk安装目录下include 及include/linux 使用”g++ -shared -I 头文件路径”解决.
8.有了具体实现的动态库后,就可以运行JAVA调用JNI程序类的native方法了。命令:
java -Djava.library.path=. com.magc.jni.HelloWorld
输入结果即为:From jni_helloworldImpl.cpp :Hello world !