JavaVM.AttachCurrentThread produces segfault

Enno Brehm
20 Sep 2001 20:12:51 +0200

Content-Type: text/plain
Content-Transfer-Encoding: 7bit


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

static inline
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 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.c). The command I used to compile the c-file was
gcc -g -I /usr/local/include/kaffe -lpthread -s -o  

Thanks for any help.

Enno Brehm

enno brehm
convergence integrated media gmbh

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);

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");

    (*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;

Content-Type: text/x-java
Content-Disposition: attachment;
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();

    static {