1、Java调用C++程序过程
Java作为一种跨平台语言,通过虚拟机的机制能够很好的将代码迁移到各个平台,但是有时候需要调用平台底层的功能,这时候往往需要利用C/C++语言进行底层代码的编写以达到很好的性能。那如何使Java能够方便的调用C/C++程序呢?本文将以一个“hello Word”基础程序给你讲解如何利用Java调用C++程序(该技术称为JNI技术)。其主要过程包括5步骤:1、编写Java本地调用程序;2、对Java程序进行编译;3、编写C/C++实现代码;4、生成动态库(dll);5、进行调用。
1.1 编写Java本地调用程序
先上代码,如下所示:
public class JNITest { static { Sy("JNITest"); // 1、定义需要加载的dll库名称 } public static native void sayHelloWorld(String msg); // 2、利用native关键字定义调用接口 public static void main(string[] args) { sayHelloWorld("Hello, world"); // 3、在主方法中进行调用 } }
主要包含3个部分,首先通过Sy()方法进行dll文件的声明,让Java程序知道需要加载哪个dll文件;其次利用native关键字定义Java调用C/C++语言的接口,该接口将由C/C++进行具体实现,注意在方法前一定要标注native关键字,因为利用native关键字标注的方法,让Java虚拟知道该方法的实现是由外部程序实现,而不是由Java程序实现;最后为了方便后面的调试,需要定义一个主方法并对sayHelloWorld进行调用。
1.2 对Java程序进行编译
在Windows系统通过菜单键+R并输入cmd命令,调出命令行窗口,并通过cd命令,将执行目录切换到1.1步骤中java文件所在的文件目录中。然后在命令行中输入javac JNITe对该java文件进行编译,如下图所示:
Java程序进行编译
在这个过程中需要注意两点问题,首先JDK的路径是否加入到系统的环境变量中;其次如果java文件带有包地址,需要将java文件的包地址写上。
输入上述命令后,在java文件所在的目录下将生成JNITe文件,该文件就是编译后的文件。然后在命令行中输入javah JNITest将生成C/C++的头文件(JNITe),如下图所示:
生成头文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include jni.h /* Header for class JNITest */ #ifndef _included_JNITest #define _Included_JNITest #ifdef __cplusplus extern "C" { #endif /* * Class: JNITest * Method: sayHelloWorld * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_JNITest_sayHelloWorld (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif
从上面的代码可以看出在JNITe文件中定义了java中的native接口。
1.3 编写C/C++实现代码
首先在vs2019 “文件-》新建-》项目”中创建C++动态程序,其创建过程如下图所示:
新建dll库
然后在右侧的项目中点击“源文件”并鼠标右键,依次选择“添加-新建项”,将弹出如下界面,并选择“C++文件”,来创建空白C++文件。
创建新的C++文件
再然后将JNITe中的声明方法拷贝到该文件中并实现具体的实现。代码如下图所示:
#include "; #include "JNITe" // 1.申明引用的头文件,该头文件就是用javah生成的头文件 // 2.该方法申明,必须要与JNITest中的声明一致, JNIEXPORT void JNICALL Java_JNITest_sayHelloWorld (JNIEnv *env, jclass, jstring string) { // 3.具体实现,获取java传过来的参数进行输出 const char* str = env->GetStringUTFChars(string, 0); char cap[128]; strcpy_s(cap, str); //env->ReleaseStringUTFChars(string, str); printf(str); }
然后,在VS2019右边的项目目录中点击“头文件”鼠标右键,并依次点击“添加-》现有项”,将用javah生成的JNITe头文件添加到项目中,添加后如下图所示:
1.4 生成动态库(dll)
编写好代码后,在vs2019右边的项目目录中,点击项目名称,并点击鼠标右键,在弹出的选择框中选择“生成”对代码进行编译。编译成功后,将会在项目的debug文件下生成相应的dll文件,其余文件不用管。如下图所示:
生成dll结果
1.5 进行调用
将1.4中生成的dll拷贝到1.1中的java文件夹下,并将dll文件的名称更改为JNITest(该名称需要与Sy()一致),然后在命令行中输入“java JNITest”,将出现如下结果,说明调用成功。
进行调用
2、出现的问题及解决过程
在实际的开发过程中,出现了两种问题,现将遇到的问题及解决方法,与大家进行分享。
1、报错无法找到jni文件
在C/C++程序进行编译的过程,出现如下的编译错误,如下图所示:
这说明vs环境未能找到jni.h头文件,该头文件存在与你JDK的include文件夹中,但是该jni.h还引用其他文件,为了保险起见,需要将jdk中的include文件夹和该文件夹下的window32文件夹加入到当前的项目中,具体的操作为,在vs2019右侧的项目目录中点击项目名,并鼠标右键,选择“属性”,弹出如下对话框:
在包含目录中添加jdk相应的路径,如下图所示:
然后进行重新编译即可。
2、在进行java调用时,出现Can't load IA 32-bit .dll on a AMD 64-bit platform错误
这是由于你生成的dll是32位的,然而Java的jdk是64位的导致的。解决方法,有两种方法,一种是更换jdk版本变更成32位的;另一种采用X64重新对dll进行编译,其具体的操作过程为:1、在vs2019顶部选择“生成-》配置管理器”,如下图所示:
在上图中“平台”选项中选择正确的平台,然后进行重新编译,即可解决该类问题。