JNI——手工编译HelloJNI

JNI——手工编译HelloJNI

原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处、作者信息和本声明。否则将追究法律责任。http://blog.csdn.net/taotaoyouarebaby/article/details/8747580


介绍


JVM封装了各种操作系统实际的差异性的同时,提供了JNI技术,它是一种双向的接口,使得开发者可以通过Java代码调用到各种native的 库,反之亦然。所以JNI(Java Native Interface)能作为Java语言的一部分,她能够作为粘合剂将Java应用和其他本地应用(C/C++,Delphi)集合在一起.

下图就很好的描述了JNIJava应用中的地位和角色:

                  

作为一个双向的接口,JNI能支持两种native代码:native libraries native applications.

(1)你能使用JNI去写一些native methods去允许Java Applications能呼叫native libraries中的函数,native methods的具体实现是可能C,C++或者Delphi

(2)JNI也支持嵌入一个JVM实现到一个本地应用程序中去,去执行那些用Java语言编写的的模块.比如,一个C++编写的浏览器利用内嵌的JVM去执行下载到本地的applet.

实现JNI-Java invoke Native Library的一般步骤如下:

1) 完成Java代码,编写好Java调用类

2)编译你的Java

3)javah生成编译好的class文件对应的C/C++  函数的头文件

4) 实现头文件中的函数原型,编写native代码

5) native代码编译打包成DLL(win32)或共享库(Linux)

6)将你的Java代码跑起来


手工编译HelloJNI


环境与工具:


win7 x64

jdk1.7.0

vs 2012 compiler for x64

当前目录:E:\programming\practice\java\JNI


编写java代码


//HelloJNI.java

package edu.zt.jni;

public class  HelloJNI

{

public native void sayHello();

public static void main(String[] args) 

{

System.loadLibrary("hellojni");

new HelloJNI().sayHello();

}

}

编译HelloJNI.java

javac -d . HelloJNI.java


导出C/C++函数头文件


javah edu.zt.jni.HelloJNI

得到edu_zt_jni_HelloJNI.h

#include <jni.h>

#ifndef _Included_edu_zt_jni_HelloJNI

#define _Included_edu_zt_jni_HelloJNI

#ifdef __cplusplus

extern "C" {

#endif

JNIEXPORT void JNICALL Java_edu_zt_jni_HelloJNI_sayHello

  (JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

注意到上面的头文件中包含了一个外部头文件jni.h,该头文件可以从%jdk%\include\中找到。但是在jni.h中还包含了jni_md.h文件,此文件位于%jdk%\include\win32中。

于是将jni.hjni_md.h文件复制到当前目录,并将edu_zt_jni_HelloJNI.h文件中的

#include <jni.h> 改为 #include jni.h

注:如果不想每次都这么麻烦呢,可以将jni.h和jni_md.h文件所在目录添加到INCLUDE环境变量中(没有则新建)。这样就无需拷贝也无需进行上面的修改。但是,每修改了环境变量都要重启一次命令行。才可以应用更改。


编写native代码

//HelloJNI.c

#include <stdio.h>

#include "edu_scu_jni_HelloJNI.h"

JNIEXPORT void JNICALL 

Java_edu_scu_jni_HelloJNI_sayHello(JNIEnv * env, jobject obj)

{

printf("Hello JNI!");

}


编译native代码为DLL


因为本机使用的是64位的java VM,所以需要编译为64位的程序,因为也就需要为64位程序设计的编译器。在此,我使用vs201264位编译器进行编译。

找到:开始菜单->Microsoft Visual Studio 2012->Visual studio tools->VS2012 x64 Cross Tools Command Prompt。点击即可打开为编译64位程序配置好的命令行(主要是设置了一些PATHLIB)。

该命令行具体配置了什么内容可以查看vcvarsall.bat文件。

查看VS2012 x64 Cross Tools Command Prompt快捷方式的属性,目标位置有以下内容:

%comspec% /k ""D:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86_amd64

转到当前工作目录,编译HelloJNI

cl /c HelloJNI.c

此外要生成DLL文件还需要一个.def文件。

//hellojni.def

LIBRARY HelloJNI

EXPORTS

Java_edu_scu_jni_HelloJNI_sayHello @1

连接HelloJNI生成DLL

link /def:HelloJNI.def /dll HelloJNI.obj

可能会出现如下警告

warning LNK4197: export xx specified multiple times; using first specification

但无关紧要。

至此hellojni.dll文件成功生成!


运行


java edu.zt.jni.HelloJNI

出现

Hello JNI!

至此方为成功!


JNI的优缺点

JNI 编程在软件开发中运用广泛,其优势可以归结为以下几点:

1 利用 native code 的平台相关性,在平台相关的编程中彰显优势。

2 对 native code 的代码重用。

3 native code 底层操作,更加高效。

然而任何事物都具有两面性,JNI 编程也同样如此。程序员在使用 JNI 时应当认识到 JNI 编程中如下的几点弊端,扬长避短,才可以写出更加完善、高性能的代码:

1 从 Java 环境到 native code 的上下文切换耗时、低效。

2 JNI 编程,如果操作不当,可能引起 Java 虚拟机的崩溃。

3 JNI 编程,如果操作不当,可能引起内存泄漏。

4 使应用失去了跨平台的能力,如果要移植到别的平台就需要重写native代码。


HelloJNI文件列表



参考


http://blog.csdn.net/todototry/article/details/1638849 如何手工编写动态链接库(windows dll) 

http://blog.csdn.net/ididcan/article/details/6828982 JNI简单实现Java调用C++/CHelloWorld

传智播客_王择佑_JNI第一讲

http://www.ibm.com/developerworks/cn/java/j-lo-jnileak/index.html?ca=drs- 在 JNI 编程中避免内存泄漏

问题:

jni.h的实现文件(dll库)在哪里,这个我还没有整明白。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值