Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > JNI callback from Tomcat using FindClass

Reply
Thread Tools

JNI callback from Tomcat using FindClass

 
 
colm.dougan@gmail.com
Guest
Posts: n/a
 
      02-23-2006
Hi,

I've inherited some code that uses JNI from Tomcat to call down to C to
initialise/subscribe to some messaging with a callback the other way (C
to Java) when a message is going to be passed back up to Java. This
used to work fine but a change of platform (slightly older Tomcat/4.1
than befoe, upgrade to latest Java 1.4.2 from 1.4.0) it has stopped
working.

The offending code is below (debug statements removed for brevity). It
fails on the FindClass(). It seems that the class loader is not the
one it expects to have. It seems to be assumed that the tomcat
classloader will be used but this doesn't seem to be the case. I have
been reading various internet knowdlege bases that imply that FindClass
will use the system/boot class loader and so this shouldn't work at
all. But how could it ever have worked? Was it previously relying on
bugs? Or is this a reasonable thing to do as the VM is kept attached.

I tried some things suggested on various sites/groups to hold a pointer
to the jobject initially passed down from Java to C in the native
method using env->NewGlobalRef(jobj); When I used the jobj later it
either crashed my tomcat or the GetStaticMethodID returned 0. I'm
aware there may be threading issues with that approach.

Any advice? I'm primarily interested in what the "right thing" is to
do here because it is not clear to me and I'm new to JNI. Is this even
the rigtht what to do callbacks of this type?

Thanks,
Colm


// a static instance of this class is held globally
// ...

int CommJNIHandler::setupThread( JNIEnv **env )
{


// JavaVM *m_pjVM is a private member variable
int rv = m_pjVM->GetEnv((void**)env, JNI_VERSION_1_2 );
if ( rv != JNI_OK )
{
if ( m_pjVM->AttachCurrentThread((void**)env, NULL) != 0 )
return -1;
}
return 0;
}


int CommJNIHandler::doCallBack ( int pMsgData ) {
JNIEnv *env;
if ( setupThread( &env ) != 0 )
{
return -1;
}

jclass cls = env->FindClass("COM/name/of/class");
if (env->ExceptionOccurred()) {
env->ExceptionDescribe();
return -1;
}

jmethodID mid = env->GetStaticMethodID(
cls, "executeMessageHandlerFromNative", "(I)I" );

if ( mid == 0 )
{
return -1;
}

int nRet = env->CallStaticIntMethod( cls, mid, (jint)pMsgData );
if ( env->ExceptionOccurred() )
{
env->ExceptionDescribe();
env->ExceptionClear();
}

return nRet;
}

 
Reply With Quote
 
 
 
 
Chris Uppal
Guest
Posts: n/a
 
      02-24-2006


http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> The offending code is below (debug statements removed for brevity). It
> fails on the FindClass(). It seems that the class loader is not the
> one it expects to have. It seems to be assumed that the tomcat
> classloader will be used but this doesn't seem to be the case. I have
> been reading various internet knowdlege bases that imply that FindClass
> will use the system/boot class loader and so this shouldn't work at
> all. But how could it ever have worked? Was it previously relying on
> bugs? Or is this a reasonable thing to do as the VM is kept attached.


It's difficult to be sure what's going on here. I think it depends on things
like how you use C++ threads, when callbacks are invoked, and perhaps even on
where your .classfiles are kept

Here's how I understand it.

FindClass() uses the classloader of the Java code where the currently executing
native method is defined. It not clear from the spec what happens in other
cases, but I /assume/ that you are in JNI code because you are using the
invocation API (not the case for your application) then it'll use the system
classloader. I also assume (which may be relevant -- see below) that when the
DLL (or equivalent) is initialised (the JNI_OnLoad() handler function in the
DLL) that FindClass() will use the classloader of the class which is calling
System.loadLibrary(). Lastly, I assume that if a C++ thread (i.e. started from
C++ and calling AttachCurrentThread(), rather than from Java code), uses
FindClass() then that will use the system classloader.

NB: all the above assumptions are /only/ assumptions -- i.e. I don't know for
sure (although they seem reasonable).

So, which classloader will be used depends on which code looks for it. (Nice
and simple isn't it . From your code snippet it appears that you are using
independent C++ threads, which might be one source of your problems. If you
are, then I suggest either doing the FindClass() in the DLL's JNI_OnLoad(), or
in some native method which is used to initialise your sub-system (if there is
one). You would then have to cache a global reference to it (as you have
already tried). Other than that, I don't see a problem with invoking
callbacks from off-thread (assuming the code is correct).

Possibly the change in Tomcat versions causes a difference in the
initialisation order, or something similar so that the FindClass() happens in a
different context -- but that's pure guesswork.

OTOH, if your JNI code is invoked from Java, so that the callbacks are just
calls back "up the stack" as it were, then I don't see why you should be having
problems at all, so maybe the problem is caused by something else entirely.

Another issue which may be relevant (probably not, but I'll mention it anyway),
is that JNI will only load each DLL for one classloader. So if you have
multiple applications under Tomcat which use the "same" class (and its native
code) then you /have/ to put that class in the shared classes area. You can't
have native code duplicated in two applications, it has to be shared.

-- chris


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
JNI FindClass problem Praetorian Java 3 07-09-2009 10:29 AM
JNI Trouble calling FindClass from Worker thread maverick Java 4 07-18-2006 09:57 AM
JNI FindClass(java/lang/string) causes core dump on AIX 5.2 abhijit.dhariya@gmail.com Java 2 03-31-2006 08:00 PM
JNI (C++): NewGlobalRef() required for FindClass() / GetFieldID() / GetStaticMethodID() ? FBergemann Java 3 04-06-2005 05:41 PM
Cannot find my JAVA class with JNI FindClass from C++ Steve Java 3 12-31-2003 03:24 PM



Advertisments