最近一段时间公司有需求要用C++调用JAVA,研究了几天,写了一个DLL,有点心得,写点东西留作记念
开发环境:VC6.0 + jdk1.5
1:首先设置好系统环境变量path,在最后面加上jvm.dll的路径(我的机器是:D:/JavaDev/jdk1.5.0_05/jre/bin/client)
2:在VC中设置的jvm的包含头文件,本机的配置为(D:/JavaDev/jdk1.5.0_05/include,D:/JavaDev/jdk1.5.0_05/include/win32)
3:在VC中设置的jvm的lib文件,本机为:D:/JavaDev/jdk1.5.0_05/lib
4:在工程选项中包含jvm.lib
5:用javap -s -p 要调用的class文件 生成要调用函数的原形。例:javap -s -p OMASServiceException
生成文件如下:Compiled from "OMASServiceException.java"
public class com.ce.omas.interfaces.exception.OMASServiceException extends java.
lang.Exception{
private static final long serialVersionUID;
Signature: J
private java.lang.String errorCode;
Signature: Ljava/lang/String;
private java.lang.String errorMessage;
Signature: Ljava/lang/String;
public com.ce.omas.interfaces.exception.OMASServiceException(java.lang.String);
Signature: (Ljava/lang/String;)V
public java.lang.String getMessageCode();
Signature: ()Ljava/lang/String;
public java.lang.String getMessage();
Signature: ()Ljava/lang/String;
}
其中我们需要的是两部分:函数名和它的Signature(参数)
6:加载jvm,大家可上网查询。需要注意的是它的JavaVMOption参数options[1].optionString,可以用来加载你自己设置的jar包,我用的是绝对路径,否则可能找不到要加载的jar包。例如:
options[1].optionString = "-Djava.class.path=.;c://1.jar;c://2.jar;"
7:调用方法。调用方法分为三个步骤:1),查找类,2),查找方法, 3),构造对象,4),调用方法
1)jclass voauth_cls = env->FindClass("com/ce/omas/omasservice/vo/CompomentInfoVO");
2)jmethodID vomethod = env->GetMethodID(voauth_cls, "<init>", "()V"); 其中第四个参数可以查看第五步生成的
Signature(参数),这个方法是用查找构造方法
3)jobject demo = env->NewObject(voauth_cls, vomethod); //构造对象
4)调用方法 java中的函数为 public boolean checkUserCount(int i)
jint ji = currentUserCount; //函数参数
bool result = env->CallBooleanMethod(obj,vomethod , ji);
目前遇到一个很引人头痛的问题,我生成的是一个DLL,从Exe中调用它时,好像DLL中的虚拟机环境(JNIEnv *env),jclass,jobjec好像不能共享,也就是每调用一次函数
我就得重新取一次它们,例如: JNIEnv* env;//虚拟机环境
jvm->AttachCurrentThread((void**)&env, NULL);
jclass cls = FindClass(...);
jmethodID id= FindMethodID(...);//查找构造函数
jobject obj = NewObject(...)//生成对象
调用完函数之后又得释放:jvm->DetachCurrentThread();
本来我是把虚拟机环境(env),要查找的类 (jclass), 生成的对象(jobject)放在DLL中某个类的成员变量中,但是测试时调用某个类第一个函数成功,再调用此类的另一个函数却失败了! 希望能得到大家指正!