JavaVM.AttachCurrentThread produces segfault
Enno Brehm
kaffe@rufus.w3.org
20 Sep 2001 20:12:51 +0200
--=-g6/Ytx7uMQJhak3ya2VO
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hello,
I've got some problems with the attachment of a thread to the VM: I need
a thread (on the native side) which does some work concurrently to the
rest of the application. This thread will need to make some callbacks
into Java objects. When I create a a thread (java.lang.Thread) on the
java side and use it, everything seems fine. but actually I want to
create the thread during some native initialization routine using the
pthread-library (my kaffe is compiled to use unix-pthreads). When this
thread then wants to call back into java, it tries to attach to the
running VM using AttachCurrentThread form the InvocationInterface to
acquire a valid JNIEnv. It *will get* a pointer, but when it really
tries to use it (say, call 'FindClass' on it), I will cause a
segmentation fault. (As far as I can see this is due to the fact that
somehow the following function from
.../systems/unix-pthreads/thread-impl.h
static inline
void*
jthread_getcookie(jthread_t tid)
{
return (tid->thread);
}
gets called with an actual value of NULL, causing the crash. This seems
to happen inside the macro BEGIN_EXCEPTION_HANDLING(X), which contains a
call to getCurrentThread()). When I do the same with the thread that
originally came from the java side, everything works fine (even if it
uses AttachCurrentThread)
Reading the JNI-Spec, I found, that the VM is supposed to create a
java.lang.Thread-Object whenever some new threads attaches itself using
AttachCurrentThread(...), but all that this function will do is to pass
out a pointer to some global JNIEnv - I expected it to create some
thread-specific structures ... anybody able to comment this? I don't
think I am doing s.th. wrong here, because it run's quite well with
JRE1.3.1, JDK1.1.8 (SUN), JDK1.3 (IBM). I am using the CVS-version of
kaffe 1.0.6 on SuSE linux 7.2 with kernel version 2.4.6.
Attached you will find a small test program that reproduces this bug
(Threads.java, Threads.c). The command I used to compile the c-file was
gcc -g -I /usr/local/include/kaffe -lpthread -s -o libThreads.so
Thanks for any help.
Enno Brehm
----------
enno brehm
convergence integrated media gmbh
--=-g6/Ytx7uMQJhak3ya2VO
Content-Type: text/x-c
Content-Disposition: attachment; filename=Threads.c
Content-ID: <1001009350.877.199.camel@fpcm>
Content-Transfer-Encoding: 7bit
#include <jni.h>
#include <stdio.h>
#include <pthread.h>
JavaVM *theVM = NULL;
void* doCallback(void* p_obj);
JNIEXPORT void JNICALL
Java_Threads_foo(JNIEnv* env, jobject obj)
{
pthread_t thread;
printf("original env %p\n", env );
if( theVM == NULL )
(*env)->GetJavaVM(env, &theVM);
// globalizing object reference for use in other thread
obj = (*env)->NewGlobalRef(env, obj);
printf("creating new thread\n");
pthread_create( &thread, NULL, doCallback, (void*)obj );
pthread_join( thread, NULL );
printf("back to old thread, doing the same\n");
doCallback(obj);
(*env)->DeleteGlobalRef(env, obj);
printf("native part finished\n");
}
/* this method will acquire a valid environment via
the JNIInvocationInterface and the pointer to the JavaVM
*/
void* doCallback(void* p_obj) {
JNIEnv* env = NULL;
jclass clazz;
jmethodID callback;
jobject obj = (jobject)p_obj;
printf("env before: %p\n", env);
(*theVM)->AttachCurrentThread(theVM, &env, NULL);
printf("env after: %p\n", env);
clazz = (*env)->GetObjectClass(env, obj);
if( (*env)->ExceptionOccurred(env) != NULL ) return NULL;
callback = (*env)->GetMethodID(env, clazz, "callback", "()V");
if( (*env)->ExceptionOccurred(env) != NULL ) return NULL;
printf("going to call method %d in class %d on obj %d\n", callback, clazz, obj);
(*env)->CallVoidMethod(env, obj, callback);
return NULL;
}
--=-g6/Ytx7uMQJhak3ya2VO
Content-Type: text/x-java
Content-Disposition: attachment; filename=Threads.java
Content-ID: <1001009354.877.200.camel@fpcm>
Content-Transfer-Encoding: 7bit
class Threads {
private native void foo();
void callback() {
System.out.println("on the java side");
}
public static void main(String[] args) {
new Threads().foo();
System.exit(0);
}
static {
System.loadLibrary("Threads");
}
}
--=-g6/Ytx7uMQJhak3ya2VO--