牛骨文教育服务平台(让学习变的简单)
博文笔记

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

创建时间:2016-12-05 投稿人: 浏览次数:3147

摘要:本文介绍了如何使用命令行工具来编写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
");
    return;
}

4.生成共享库
4.1 Windows 32位生成共享库
这里需要特别注意一点,在Windows的Cmd命令行中,如果你的路径中带有空格,需要额外进行处理。 具体处理方法,可参考文献[4],这里仅举个例子来简单说明。 echo %JAVA_HOME C:Program FilesJavajdk1.8.0_102 那么,需要执行以下命令来生成32位dll: gcc -I C:PROGRA~1Javajdk1.8.0_102include -I C:PROGRA~1Javajdk1.8.0_102includewin32 -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)
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。