操作环境为win10,VC6.0,JDK1.8.0_191(x86)。
因为项目需要,在网上查看了很多相关文章,都没能复现,反而是将多篇文章相结合才成功了,可以说过程相当熬人,弄了两三天差点放弃。接下来说说整个调用过程。主要参考这篇文章《从 C/C++ 程序调用 Java 代码》,当然前面还说了借鉴了其他很多文章,但是记不清是哪些了,都大同小异,有兴趣可以去网上进行相关搜索。
C++调用JAVA主要用到了SUN公司的JNI技术,我们也是通过jni来实现的。
-
配置JDK
首先到SUN公司网站可以下载JDK1.8.0_191(x86)。然后是配置相关的环境变量,可以参考这篇百度经验。 -
编写Java代码
学过Java的,这个步骤就没什么困哪,我也简单的说一下。
首先在所以哪个盘下创建一个文件夹“com”,就比如说在F盘下,然后在里边创建一个名字为demo.txt文本,在里面创建如下代码:
package com;
public class demo {
public demo(){ //Constructor
super();
}
public static int add(int a,int b){
return a+b;
}
public boolean judge(boolean bool){
return !bool;
}
}
然后将demo.txt的扩展名改为.java,文本就变成了demo.java。
打开命令行(win+R,输入cmd),打开.java所在文件
然后输入javac demo.java 来编译java文件
然后在demo.java所在文件夹里就出现了 demo.class文件,这个是我们需要的。
到这里java编译成功。
- 配置VC6.0
添加库目录
通过VC++ 6的菜单 “工具→选项” 打开选项对话框,找到“目录”下的“include files”,添加
C:\Program Files (x86)\Java\jdk1.8.0_191\include
C:\Program Files (x86)\Java\jdk1.8.0_191\include\win32
这两个路径
再在“Library files”下添加
C:\Program Files (x86)\Java\jdk1.8.0_191\lib
- 编写C++代码
用VC6.0创建MFC项目。
在对话框中添加一个编辑框和一个按钮,给编辑框设置变量m_edit1
在Dlg.h文件中添加头文件“
#include <jni.h>
#include <stdlib.h>
由于JVM只能创建一次!!!所以我们JVM需要我们在OnInitDialog()里面创建。
我们在Dlg.h文件里面添加成员变量
protected:
HICON m_hIcon;
//一下为添加的变量
CString javapath;
JavaVMOption options[3];
JNIEnv *env;
JavaVM *jvm; //java虚拟机
JavaVMInitArgs vm_args;
long status;
jclass cls; //java class
jmethodID mid; //java方法
jint square;//java int
jboolean not; //java bool
jobject jobj;//java object
HINSTANCE hInstance;
在OnInitDialog()里面添加
// TODO: Add extra initialization here
javapath=getenv("JAVA_HOME");//获取环境变量
//找到jvm.dll 的路径,用于创建虚拟机
javapath+="\\jre\\bin\\server\\jvm.dll";
CString zx =javapath;
m_edit1+=zx+"\r\n";
//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来
options[0].optionString = "-Djava.class.path=.;F:\\";
options[2].optionString = "-verbose:NONE";
//设置版本号,版本号有JNI_VERSION_1_1,JNI_VERSION_1_2和JNI_VERSION_1_4
//选择一个根你安装的JRE版本最近的版本号即可,不过你的JRE版本一定要等于或者高于指定的版本号
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
//该参数指定是否忽略非标准的参数,如果填JNI_FLASE,当遇到非标准参数时,JNI_CreateJavaVM会返回JNI_ERR
vm_args.ignoreUnrecognized = JNI_TRUE;
typedef jint(WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *);
//加载JVM.DLL动态库
hInstance = ::LoadLibrary(javapath);
if (hInstance == NULL)
{
zx="加载链接库失败\r\n";
m_edit1+=zx;
zx.Format("%d",GetLastError());
m_edit1+=zx;
UpdateData(FALSE);
}
else
{
zx="加载链接库成功\r\n";
m_edit1+=zx;
//取得里面的JNI_CreateJavaVM函数指针
PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
//调用JNI_CreateJavaVM创建虚拟机
status = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
if (status != JNI_ERR)
{
zx="JVM虚拟机创建成功\r\n";
m_edit1+=zx;
}
else
{
m_edit1+="JVM虚拟机创建失败\r\n";
}
}
UpdateData(FALSE);
给按钮添加单击事件
void CMfcjavaDlg::OnButton1()
{
CString zx;
if (status != JNI_ERR)
{
//查找test.Demo类,返回JAVA类的CLASS对象
cls = env->FindClass("com/demo");
if (cls != 0) {
zx="自定义类加载成功\r\n";
m_edit1+=zx;
mid = env->GetStaticMethodID(cls, "add", "(II)I");
if (mid != 0) {
square = env->CallStaticIntMethod(cls, mid, 5, 5);
zx.Format("%d",square);
zx="ans="+zx;
m_edit1+=zx+"\r\n";
}
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
mid = env->GetMethodID(cls, "<init>", "()V");
if (mid != 0) {
jobj = env->NewObject(cls, mid);
m_edit1+="init ok\r\n";
}
mid = env->GetMethodID(cls, "judge", "(Z)Z");
if (mid != 0) {
not = env->CallBooleanMethod(jobj, mid, 1);
if (!not) {
m_edit1+="Boolean ok\r\n";
}
}
}
//jvm->DestroyJavaVM();
}
else
{
m_edit1+="-1\r\n";
}
m_edit1+="end\r\n";
//::FreeLibrary(hInstance);
UpdateData(FALSE);
}
关闭程序时要
//销毁虚拟机并释放动态库
jvm->DestroyJavaVM();
::FreeLibrary(hInstance);
到此就成功了,编辑框显示
C:\Program Files (x86)\Java\jdk1.8.0_191\jre\bin\server\jvm.dll
加载链接库成功
JVM虚拟机创建成功
自定义类加载成功
ans=10
init ok
Boolean ok
end