您的位置:首页 > 编程语言 > Java开发

Java Jni入门(一):Hello Jni(在Java中调用C库函数)

2016-12-05 07:12 555 查看

摘要:本文介绍了如何使用命令行工具来编写Jni程序,以实现Java中调用C库函数的功能。

包含Windows 32位、Windows 64位、Linux、Mac OS三种环境。

    前提条件:
1. 已经安装好JDK,并配置好环境变量
2. Windows 32位已安装并配置好Cygwin可正常使用gcc
3. Windows 64位尚未完成,完成后更新
4. Linux已安装并配置好gcc命令行工具
5. Mac OS在terminal下,可正常使用gcc命令行工具

6. 能编写简单Java代码
7. 能看懂简单C语言代码

    在Java中调用C库函数主要分为6个步骤:
1. 编写Java代码
2. 生成C语言头文件
3. 编写C代码
4. 生成C共享库
4.1 Windows 32位生成C共享库
4.2 Windows 64位成成C共享库
4.2 Linux生成C共享库
4.3 Mac生成C共享库
5. 编译Java代码
6. 运行Java程序

    分步详解:
1. 编写Java代码
在当前目录下,创建HelloJni.java文件,代码如下:
public class HelloJni {

native void hello();

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

public static void main(String args[]) {
HelloJni helloJni = new HelloJni();
helloJni.hello();
}
}

2. 生成C语言头文件
在当前目录下,已可以看到HelloJni.java,在命令行工具中,执行javah HelloJni命令(注意:不是HelloJni.java)。
此时,可看到在当前目录下,有HelloJni.java和HelloJni.h,HelloJni.h,代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJni */

#ifndef _Included_HelloJni
#define _Included_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     HelloJni
* Method:    hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJni_hello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


3.编写C代码
在当前目录下,创建HelloJni.c(或HelloJni.cpp)文件,代码如下:

#include "HelloJni.h"

JNIEXPORT void JNICALL Java_HelloJni_hello
(JNIEnv *env, jobject obj)
{
printf("Hello Jni\n");
return;
}

4.生成共享库

4.1 Windows 32位生成共享库

这里需要特别注意一点,在Windows的Cmd命令行中,如果你的路径中带有空格,需要额外进行处理。
具体处理方法,可参考文献[4],这里仅举个例子来简单说明。
echo %JAVA_HOME
C:\Program Files\Java\jdk1.8.0_102
那么,需要执行以下命令来生成32位dll:
gcc -I C:\PROGRA~1\Java\jdk1.8.0_102\include -I C:\PROGRA~1\Java\jdk1.8.0_102\include\win32 -shared -Wl,–kill-at -s -o Hello.dll HelloJni.c


4.2 Windows 64位生成共享库
注意:使用编译出来的32位dll库,会与之不兼容。
目前,只编译出来了32位dll库。之后,完成了64位dll库编译,会再更新博客。

4.3 Linux生成共享库
在当前目录下,执行echo $JAVA_HOME,查看JDK路径,之后的命令都会基于JDK路径。
比如,echo $JAVA_HOME,结果为/usr/local/jvm/openjdk-1.8.0-internal

4.3.1 编译并生成.o文件
g++ -I /usr/local/jvm/openjdk-1.8.0-internal/include -I /usr/local/jvm/openjdk-1.8.0-internal/include/linux/ -fPIC -c HelloJni.c

4.3.2 编译并生成.so文件
g++ -shared -Wl,-soname -o libHelloJni.so HelloJni.o

4.3.3 通知动态链接程序此共享文件的路径
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH

4.4 Mac生成共享库

在当前目录下,命令行工具中,执行如下命令:
g++ -dynamiclib -I /System/Library/Frameworks/JavaVM.framework/Headers HelloJni.c -o libHelloJni.jnilib
成功后,可看到新增libHelloJni.jnilib。
(在Mac OS环境下,动态库的命名格式为libXXX.jnilib)

5.编译java代码
在当前目录下,已可以看到HelloJni.java、HelloJni.h、HelloJni.c、 libHelloJni.jnilib。
在命令行工具中,执行javacHelloJni.java后,可看到新增HelloJni.class

6.运行java程序
在当前目录下,已可以看到HelloJni.java、HelloJni.h、HelloJni.c、HelloJni.dll(Windows环境)、libHelloJni.so(Linux环境)或libHelloJni.jnilib(Mac OS环境)、HelloJni.class。
在命令行工具中,执行java HelloJni,可看到执行结果为:
Hello Jni


参考文献:
1.《Android框架揭秘--人民邮电出版社》
2.
博客:Mac OS 环境下编译JNI(http://blog.csdn.net/codigger/article/details/9296037
3.
博客:在Linux平台下使用JNI(http://www.ibm.com/developerworks/cn/java/l-linux-jni/)
4.
博客:命令行如何处理windows含空格的目录 (http://blog.csdn.net/duanbeibei/article/details/45364407
5.
博客:在windows下使用gcc编译jni的简单教程(http://blog.csdn.net/duanbeibei/article/details/45364407
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Jni