用jni从C++中调用java

来源:互联网 发布:淘宝装修编辑器 编辑:IT博客网 时间:2019/08/18 21:28

最近一段时间公司有需求要用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中某个类的成员变量中,但是测试时调用某个类第一个函数成功,再调用此类的另一个函数却失败了!  希望能得到大家指正!