I have the following problem:
in my java program I'm calling a native function that creates an object of the "MyEventReceiver" class in C++, later in that java program I'm calling an native function that calls the "test" method of that object. In this "test"-method I want to call a method of the java object that I used to call the second native function, but as soon as make this call, the jvm crashes.
This is the native code that creates the MyEventReceiver object:
JNIEXPORT jlong JNICALL Java_irr4jEventReceiver_native_1createEventReceiver
(JNIEnv *env, jobject obj){
MyEventReceiver *rec = new MyEventReceiver(env, obj);
return (long)rec;
}
this is the native code that i use later in the program to call the "test" method in that object:
JNIEXPORT void JNICALL Java_irr4jEventReceiver_native_1testmethode
(JNIEnv *env, jobject obj, jlong ptrrec){
MyEventReceiver *rec = (MyEventReceiver*)ptrrec;
rec->test();
}
and this is the MyEventReceiver class:
class MyEventReceiver : public IEventReceiver
{
public:
JNIEnv *myenv;
jobject receiverobj;
jclass SEventclass;
jobject eventobj;
jmethodID cid;
jclass cevrec;
jmethodID meth2;
public:
void test(){
eventobj = myenv->AllocObject(SEventclass);
eventobj = myenv->NewObject(SEventclass, cid);
myenv->CallVoidMethod(receiverobj,meth2,eventobj); //this is the line that causes the crash
}
MyEventReceiver(JNIEnv *env, jobject obj)
{
this->myenv=env;
receiverobj = env->NewGlobalRef(obj);
SEventclass = myenv->FindClass("SEvent");
cid = myenv->GetMethodID(SEventclass,"<init>", "()V");
cevrec = myenv->FindClass("MyEventReceiver");
meth2 =myenv->GetMethodID(cevrec, "OnEvent", "(LSEvent;)V");
//test();
}
};
if I call the method "test" at the end of the constructor, it works... only if I make the call later out of the java program... I think it has something to do with the jobject "receiverobj"... seems to get invalid after some time but I don't know why ...I stripped the code a bit...deleted some debug code. The "eventobj" I'm creating is fine... I can call other methods of that object, the methodIDs are also fine, just the line:
myenv->CallVoidMethod(receiverobj,meth2,eventobj);
gives me problems and i dont know why :)
crash message is:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x67d594f4, pid=5292, tid=2400
#
# JRE version: 7.0_21-b11
# Java VM: Java HotSpot(TM) Client VM (23.21-b01 mixed mode, sharing windows-x86 )
# Problematic frame:
# V [jvm.dll+0xa94f4]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# G:\irr4jjava\irr4j\hs_err_pid5292.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
#
EDIT:
Thanks for the help so far. I tried to use global refs and attached thread but I can't get it to work. I'm not sure if I understood the thing with the attached thread...
I modified the first native method to create a global reference to the jobject and pass it to the constructor: JavaVM *jvm;
JNIEXPORT jlong JNICALL Java_irr4jEventReceiver_native_1createEventReceiver
(JNIEnv *env, jobject obj){
jobject recobj = env->NewGlobalRef(obj);
env->GetJavaVM(&jvm);
MyEventReceiver *rec = new MyEventReceiver(recobj);
return (long)rec;
}
in the class "MyReceiverObject" I try attach the thread but it still crashes:
class MyEventReceiver : public IEventReceiver
{
public:
JNIEnv *myenv;
jobject receiverobj;
jclass SEventclass;
jobject eventobj;
jmethodID cid;
jclass cevrec;
jmethodID meth2;
public:
void test(){
jvm->AttachCurrentThread((void**)&myenv,NULL);
eventobj = myenv->AllocObject(SEventclass); //crash
eventobj = myenv->NewObject(SEventclass, cid);
myenv->CallVoidMethod(receiverobj,meth2,eventobj);
}
MyEventReceiver(jobject obj)
{
jvm->AttachCurrentThread((void**)&myenv,NULL);
receiverobj=obj;
SEventclass = myenv->FindClass("SEvent");
cid = myenv->GetMethodID(SEventclass,"<init>", "()V");
cevrec = myenv->FindClass("MyEventReceiver");
meth2 =myenv->GetMethodID(cevrec, "OnEvent", "(LSEvent;)V");
//test();
}
};