Java本身已经足够强大,但是在某些情况下,Java也是有局限的,最大的局限在于不能直接操作硬件,因为Java是运行在JVM上的,不是直接运行于CPU。另一个原因在于相比于C/C++而言,Java的运行效率比较低,但是C/C++虽然运行效率高,且能够直接操作硬件,但是的带来的不足是,开发效率太低,那就将Java与C/C++结合起来吧!利用各自的优势,发挥最大的潜力。

这里使用的就是JNI技术,Java Native Interface(Java本地接口)

说起来也很简单,就是用Java定义业务逻辑接口,然后用C/C++是实现这些接口,并且这些实现对于Java的调用是透明的。

 

 

首先创建一个Java项目jnidemo

如下:

定义了一个UserInfo类,和一个UserService业务逻辑对象

UserInfo类,只有一个id和name成员变量

 

UserService业务逻辑类

static{}这句话待会儿说

值得注意的是这里定义了2个方法,countUser和findUserById,但是并没有实现,而且用native标注

这就说明了这两个方法是本地托管方法,通俗的说就是让C/C++去实现的方法,而Java不必去管怎么实现的。

 

 

 

好以上就是Java的工程,下面看看C/C++的工程

 

采用的IDE是Visual Stdio 2008

这里比较复杂

1.第一步,导出刚刚Java托管的UserService业务逻辑类托管的C/C++头文件

具体做法:开始->运行->cmd

然后进入到jnidemo的项目的根目录下或者bin目录(Web工程没有bin目录),

然后运行 javah -jni com.sean.jni.service.UserService(类的绝对路径)

然后在bin目录里就能看到生成的C/C++头文件

 

 

 

下面开始创建C/C++工程

 

利用VS创建一个MFC dll工程

并且将生成的头文件com_sean_jni_service_UserService.h拷贝到工程中

还要将jni.h(在%JAVA_HOME%/include目录中)和jni_md.h(在%JAVA_HOME%/include/win32目录中)这两个头文件一起拷贝到工程中

 

 

然后就要开始写代码了

创建UserService.cpp文件(也可以.c文件)

代码如下

 

可以看到这里实现了2个方法正是Java托管的接口countUser和findUserById

 

为了简单起见,在countUser直接返回100,

而在findUserById方法里,通过java传进来的Id,创建一个UserInfo对象,id = java传进来的Id,name = “Sean”,并返回给Java。

如果对Java反射比较熟悉的话,可以看到,在C++实现的这部分代码,是不是有点反射的味道?

恩,这就对了。

 

 

 

 

好,C/C++的工程就完了,接下来的要做的就是连接Java和C/C++

编译C/C++工程后,在工程的debug目录中会生成一个dll文件,JNIDemo.dll(具体的文件名是工程的名称)

好,要的就是这个dll文件,dynamic link library(动态链接库)

 

 

 

将这个dll拷贝到java工程中,可以新建一个dll代码文件夹(随意)

 

 

然后在UserService这个java类中,添加一句代码

static {         System.loadLibrary("dll/JNIDemo"); }

 

没错,就是将这个库导入到java工程中

 

 

 

到此为止,整个工程就完结了,实现了java调用C/C++,来处理业务逻辑

 

 

 

下面写个测试函数来看看吧

代码很简单

首先调用countUser方法,统计总共多少人?刚刚在C/C++工程里返回的是100,所以应该打印出100

 

然后调用findUserById(10000),参数为10000,所以返回来的用户对象,id=10000,name=Sean

 

为了测试java调用C/C++的效率,这里还统计了调用的时间

 

 

上面代码的运行情况应该是

总共人数:100

the parameter is : 10000

用户Id:10000

用户姓名:Sean

总共花费:xxx毫秒

 

运行结果

 

运行结果完全正确,而且只用了4毫秒(实际肯定小于4毫秒),虽然速度肯定比不上直接运行C/C++,但是相比Java而言,这个速度还是可以接受的。

 

 

通过这个案例,我们还可以想的远一点,虽说Java不能直接操作硬件,但是是不是可以让C/C++去操作硬件,然后用Java来直接调用呢?

答案是完全可以的,这也就说明了,Java和C/C++是可以互相协作开发的。