JNI Trouble calling FindClass from Worker thread

M

maverick

Hello
I am able to get the class object when i call FindClass in the main
thread. Now when i spawn a worker thread and attempt the same call
after caching the JVM and creating a new Env . it fails and triggers an
exception on the Java side .


My code for a DLL looks like this

JMVM *jvm = NULL ;

...
DLLMain()
{
}

JNIEXPORT jint JNICALL Initialize
(JNIEnv *pEnv, jclass)
{

pEnv->GetJavaVM(&jvm);
ASSERT(jvm!=NULL);

jclass cls = pEnv->FindClass("demoflashplugin/views/Objfactory");

if(cls!=NULL)
AfxMessageBox("cls found");


AfxBeginThread(WindowThread , NULL);

}



UINT WindowThread(LPVOID p)
{

JNIEnv *env = NULL ;
jclass cclass ;
if(jvm!=NULL)
{
if (0==jvm->AttachCurrentThread((void**)&env,NULL))
{
if ((env)->ExceptionOccurred()) {
AfxMessageBox("Exception occured");
(env)->ExceptionDescribe() ;
}
if(env!=NULL)
{
AxMessageBox(getenv("CLASSPATH"));
cclass = env->FindClass(demoflashplugin/views/Objfactory");
if(cclass!=NULL)
{
AfxMessageBox("Class is not Null");
}
else
AfxMessageBox("Class is s Null");
}
else
{
AfxMessageBox("env is NULL ");
}

AfxMessageBox("Finished checking for string");
}
else
{
AfxMessageBox("JVM IS Null");
}


}
}
 
C

Chris Uppal

maverick said:
I am able to get the class object when i call FindClass in the main
thread. Now when i spawn a worker thread and attempt the same call
after caching the JVM and creating a new Env . it fails and triggers an
exception on the Java side .
jclass cls = pEnv->FindClass("demoflashplugin/views/Objfactory"); [...]
cclass = env->FindClass(demoflashplugin/views/Objfactory");

Note that the second line won't compile -- it's worth double checking your real
code to see if you are using identical class names in both cases.

Other than that I don't see anything obviously wrong.

-- chris
 
M

maverick

actually this does compile and I am able to verify the same by stepping
inside
Chris said:
maverick said:
I am able to get the class object when i call FindClass in the main
thread. Now when i spawn a worker thread and attempt the same call
after caching the JVM and creating a new Env . it fails and triggers an
exception on the Java side .
jclass cls = pEnv->FindClass("demoflashplugin/views/Objfactory"); [...]
cclass = env->FindClass(demoflashplugin/views/Objfactory");

Note that the second line won't compile -- it's worth double checking your real
code to see if you are using identical class names in both cases.

Other than that I don't see anything obviously wrong.

-- chris
 
M

maverick

cclass = env->FindClass(demoflashplugin/views/Objfactory");

Yes this was a typo , make that
cclass = env->FindClass("demoflashplugin/views/Objfactory");


Sorry my mistake .


For some reason I cannot find the class from the thread . Inside Java
code my classpath is a .jar file . I would assume that the same
environment would be passed to the thread when i cache the JVM pointer
.. Looks like i ve really hit a stone and am not able to root cause
this . Really need some inputs for this . i still believe its some
kinda classpath issue but am not able to resolve it

actually this does compile and I am able to verify the same by stepping
inside
Chris said:
maverick said:
I am able to get the class object when i call FindClass in the main
thread. Now when i spawn a worker thread and attempt the same call
after caching the JVM and creating a new Env . it fails and triggers an
exception on the Java side .
jclass cls = pEnv->FindClass("demoflashplugin/views/Objfactory"); [...]
cclass = env->FindClass(demoflashplugin/views/Objfactory");

Note that the second line won't compile -- it's worth double checking your real
code to see if you are using identical class names in both cases.

Other than that I don't see anything obviously wrong.

-- chris
 
C

Chris Uppal

maverick said:
For some reason I cannot find the class from the thread . Inside Java
code my classpath is a .jar file . I would assume that the same
environment would be passed to the thread when i cache the JVM pointer

The JVM's classpath will be the same in all threads.

The only possibility that I can suggest is that the Java thread where the
FindClass() works is running with a custom classloader, not the primordial or
the application classloader. That would happen if a custom classloader is used
to load the class from which the DLL is initially loaded (probably in its class
initialisation). If that happened then that classloader might be able to find
Objfactory.class but the application classloader (which would be used by the
new thread's FindClass() as far as I understand this) would not be able to find
it (or worse, would find another version).

If that is the problem, then the simple solution would be to get references to
the classes you need in the DLL main(), convert them to "global" references (so
they can be used from any thread), and store them there.

If that's too inflexible, then I would be tempted to change the design a bit --
create a Java object (of a new class written for this purpose) who's job it is
to find your classes. It's class would be loaded by the custom classloader,
and so that classloader would be used whenever it used Class.byName(). You
would then initialise your DLL with a (global) instance of that class, and
would use its findClass() method instead of the JNI FindClass().

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top