本身实现一个Native方法的调用

JNIjava

开始本篇的内容以前,首先要讲一下JNI。Java很好,使用的人不少、应用极 广,可是Java不是完美的。Java的不足体如今运行速度要比传统的C++慢上许多以外,还有Java没法直接访问到操做系统底层如硬件系统,为此 Java提供了JNI来实现对于底层的访问。JNI,Java Native Interface,它是Java的SDK一部分,JNI容许Java代码使用以其余语言编写的代码和代码库,本地程序中的函数也能够调用Java层的函 数,即JNI实现了Java和本地代码间的双向交互。函数

 

Nativespa

JDK开放给用户的源码中随处可见Native方法,被Native关键字声明的方法说明该方法不是以Java语言实现的,而是以本地语言实现的,Java能够直接拿来用。这里有一个概念,就是本地语言,本地语言这四个字,我的理解应该就是能够和操做系统直接交互的语言。操作系统

 

经过JNI调用C++写的代码命令行

下面演示一下如何写一段简单的C++代码,在Java中用一个Native方法去调用的步骤。C++代码使用到的IDE是Microsoft Visual Studio 2010,这是一款市面上开发C++代码最经常使用的IDE,功能强大。OK,接下来一步一步演示一下:3d

一、写一段Java代码。因为咱们在Windows环境下,因此用的是一 个.dll文件,若是在Linux环境下的话,用的是一个.so文件。最后C++代码写完以后要生成一个.dll/.so文件,生成的文件可使用 static静态加载的方法加载进来,也能够经过配置环境变量的方式,这里选择前者。code

复制代码
 1 public class TestMain  2 {  3 static  4  {  5 System.load("D:" + File.separator + "Hello.dll");  6  }  7  8 public native static void Hello();  9 10 public static void main(String[] args) 11  { 12  Hello(); 13  } 14 }
复制代码

二、cmd进入命令行程序中,进入刚才写的那个类的CLASSPATH下,CLASSPATH就是.class文件所在的根路径。运行“JNI -jni com.xrq.test1.TestMain” ,表示为指定的类下的Native方法生成.h文件。.h文件是C/C++使用的头文件,用于将声明和实现分离,不熟悉C/C++的同窗也不用深究blog

三、进入本身的CLASSPATH底下查看一下有没有多一个.h文件,我本身这边的是开发

这个命名是javah这个命令的实现帮咱们命名的,只要多了这个文件就能够了cmd

四、打开VS2010,文件-->新建-->项目,命名为“Hello”,和咱们静态块中load进去的名字要一致

注意选择DLL

五、刚才经过javah生成的.h文件复制到Hello目录下

六、把这个.h添加到项目中,右键头文件-->添加-->现有项,选择Hello目录下的“com_xrq_test1_TestMain.h”添加进去就行了

七、右键 源文件-->添加-->新建项,选择.cpp文件,随便命名,我叫作source.cpp。实现很简单,就打印一下“Hello”这个字符 串。cout是C++的控制台输出语句,至关于Java的System.out.print(),endl是换行的意思,因此这整句至关于Java的 System.out.println("Hello");

八、修改“com_xrq_test1_TestMain.h”头文件中的#include <jni.h>为#include "jni.h"

九、把%JAVA_HOME%/include目录下的“jni.h”%JAVA_HOME%/include/win32目录下的“jni_md.h”两 个文件复制到Hello目录下,用刚才添加“com_xrq_test1_TestMain.h”同样的方式添加这两个.h文件到头文件目录中,这样目录 下Hello目录下应该多出了两个文件,VS2010工程目录下应该有3个.h文件。JAVA_HOME就是JDK安装目录,不知道的cmd进入命令行,echo %JAVA_HOME%就能够查看了。这一步很重要,没有这一步,C++程序是没法运行的

十、右键项目-->生成,就能够生成.dll文件了

十一、刚才生成的.dll文件是32系统下的,32系统的用户能够直接使用这 个.dll文件了,只要复制到静态代码块指定的目录下就行了。换句话说,64位系统的用户是不能使用这个.dll文件的。若是要生成64位计算机可使用 的.dll文件,还要额外再为64位计算机成生一个.dll文件

下拉菜单里面没有x64的点击下拉菜单-->配置管理器配置一下,本身摸索一下就行了,VS2010有自带x64的

十二、生成64位的.dll,复制到D盘下便可,也就是静态代码块里面指定的Hello.dll的路径


1三、运行一下第一步里面写的Java程序,C++打印的“Hello”就出来了,至此,Java经过JNI调用C++编写的代码的功能完成。

 

有什么心得?

本身完成了这么一个过程,确定是很有成就感的,成就感事后,咱们能够从这13个步骤中感悟到什么?至少我的有如下心得:

一、1个类中有不少Native方法-->这个类中的全部Native方法生成到1个.h文件中-->本地代码生成一个.dll/.so文件和一个类的Native方法实现相对应

二、为何有Native方法的类中必有这么一段代码

1 private static native void (); 2 static { 3  registerNatives(); 4 }

如今想来,估计和咱们的静态代码块起的做用同样,都是为这个类导入特定的.dll/.so文件用的。至于为何不能像咱们这么写,我的猜想,是由于不一样的用户磁盘上的.dll/.so文件位置不固定,和JDK安装目录相关?

三、Java不在意Native方法是用什么语言实现的,只要一来语言能和底层打 交道就行了,二来语言实现完能够提供出来.dll/.so文件。所以同一个Native方法,若是不一样的Java虚拟机去调用它,那么结果可能都不一样,比 如Object的hashCode(),固然,运行效率也不尽然相同,由于不一样的虚拟机对于不一样的Native方法有本身的实现。