[kaffe] kaffe 1.0.6, JNI & pthreads

Clemens Fuchslocher clfuit00@fht-esslingen.de
Mon, 6 May 2002 20:20:08 +0200 (CEST)


hi,

I have a problem with the java native interface and kaffe 1.0.6.

The following jni tasks are working without any problems: calling
a jni function from the java side and calling a java method from
the jni side. But if I try to call a java method out of a pthread,
which was created in a jni function previously, kaffe will crash
with an 'java/lang/StackOverflowError'. If I use the sun jdk it
works properly (see below).


System:
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
zero:~$ uname -a
 Linux foo 2.4.17 #1 Sat Apr 13 17:34:00 CEST 2002 i686 unknown

zero:~$ /lib/libc.so.6
 GNU C Library stable release version 2.2.5, by Roland McGrath et al.
 [...]
 Compiled by GNU CC version 2.95.4 20011006 (Debian prerelease).
 Compiled on a Linux 2.4.13 system on 2002-02-04.
 Available extensions:
     GNU libio by Per Bothner
     crypt add-on version 2.1 by Michael Glad and others
     linuxthreads-0.9 by Xavier Leroy
     BIND-8.2.3-T5B
     libthread_db work sponsored by Alpha Processor Inc
     NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
 Report bugs using the `glibcbug' script to <bugs@gnu.org>.

zero:~$ java -version
 Kaffe Virtual Machine
 Copyright (c) 1996-2000
 Transvirtual Technologies, Inc.  All rights reserved
 Engine: Just-in-time v3   Version: 1.0.6   Java Version: 1.1

zero:~$ javac  -version
 version number: 1.4F released 05/23/2000

zero:~$ kaffeh -version
 Kaffeh Stub Generator
 Copyright (c) 1996, 1997
 Transvirtual Technologies, Inc.  All rights reserved
 Version: 1.0.6
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=



Here is an example that produces the error mentioned above:
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
// Test.java
class Test
{
    long c = 0;

    public native void test_start_callback ();
    public native void test_stop_callback ();

    static
    {
        try
        {
            System.loadLibrary ("test");
        }
        catch (Exception e)
        {
            System.err.println ("System.loadLibrary (): " + e);
            System.exit (1);
        }
    }

    public void start ()
    {
        test_start_callback ();
    }

    public void stop ()
    {
        test_stop_callback ();
    }

    public void callback ()
    {
        System.out.println ("public void callback (): " + c++);
    }
}

class Main
{
    public static void main (String args[])
    {
        Test test = new Test ();

        test.start ();
        try
        {
            System.in.read ();
        }
        catch (Exception e)
        {
            System.err.println (e);
            System.exit (1);
        }
        test.stop ();
    }
}
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=



test_jni.c:
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <jni.h>
#include <pthread.h>

#include "Test.h"

pthread_t thread;

JavaVM *vm = NULL;
jobject obj;
static int end = 1;

static void *test_thread (void *arg)
{
    JNIEnv *env = NULL;
    jclass class;
    jmethodID callback;

    if ((*vm)->AttachCurrentThread (vm, (JNIEnv **) &env, NULL) < 0)
    {
        fprintf (stderr, "%s[%d]: AttachCurrentThread ()\n",
            __FILE__, __LINE__);
        return NULL;
    }

    class = (*env)->GetObjectClass (env, obj);

    callback = (*env)->GetMethodID (env, class, "callback", "()V");
    if (callback == NULL)
    {
        fprintf (stderr, "%s[%d]: GetMethodID ()\n",
            __FILE__, __LINE__);
        return NULL;
    }

    while (end)
    {
        (*env)->CallVoidMethod(env, obj, callback);
        sleep (1);
    }

    if ((*vm)->DetachCurrentThread (vm) < 0)
    {
        fprintf (stderr, "%s[%d]: DetachCurrentThread ()\n",
            __FILE__, __LINE__);
        return NULL;
    }

    return NULL;
}

JNIEXPORT void JNICALL
Java_Test_test_1start_1callback (JNIEnv *env, jobject object)
{
    int ret;

    end = 1;

    printf ("JNI: test_start_callback ()\n");

    if ((*env)->GetJavaVM (env, &vm) < 0)
    {
        fprintf (stderr, "%s[%d]: GetJavaVM ()\n",
            __FILE__, __LINE__);
        return;
    }

    obj = (*env)->NewGlobalRef (env, object);
    if (obj == NULL)
    {
        fprintf (stderr, "%s[%d]: NewGlobalRef ()\n",
            __FILE__, __LINE__);
        return;
    }

    if ((ret = pthread_create (&thread, NULL, test_thread, NULL)) != 0)
    {
        fprintf (stderr, "%s[%d]: pthread_create (): %s\n",
            __FILE__, __LINE__, strerror (ret));
        return;
    }
}

JNIEXPORT void JNICALL
Java_Test_test_1stop_1callback (JNIEnv *env, jobject object)
{
    int ret;

    printf ("JNI: test_stop_callback ()\n");

    end = 0;

    if ((ret = pthread_join (thread, NULL)) != 0)
    {
        fprintf (stderr, "%s[%d]: pthread_join (): %s\n",
            __FILE__, __LINE__, strerror (ret));
        return;
    }

    (*env)->DeleteGlobalRef (env, obj);
}
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=



This is how I build the jni application with kaffe:
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
zero:~$ export LD_LIBRARY_PATH=.
zero:~$ export PATH=/usr/local/kaffe/bin:$PATH
zero:~$ export CLASSPATH=.:/usr/local/kaffe/share/kaffe/Klasses.jar
zero:~$ javac Test.java
zero:~$ kaffeh -jni Test
zero:~$ gcc -Wall -I/usr/local/kaffe/include/kaffe/ -c test_jni.c
zero:~$ gcc -shared -Wl,-soname,libtest.so -o libtest.so test_jni.o \
 -lpthread
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=



The crash:
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
zero:~$ java Main
 JNI: test_start_callback ()
 Internal error: caught an unexpected exception.
 Please check your CLASSPATH and your installation.
 java/lang/StackOverflowError
 Aborted (core dumped)

[...]
zero:~$ java Main
 JNI: test_start_callback ()
 Kaffe: machine.c:214: translate: Assertion `reinvoke == false'
 failed.
 Aborted (core dumped)

[...]
zero:~$ java Main
 JNI: test_start_callback ()
 Kaffe: exception.c:372: dispatchException: Assertion
 `!intsDisabled()' failed.
 Aborted (core dumped)
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=



If I use the sun jdk 1.3.1/1.4.0 instead, everything works fine.
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=
zero:~$ export LD_LIBRARY_PATH=.
zero:~$ javac Test.java
zero:~$ javah -jni Test
zero:~$ gcc -Wall -c test_jni.c
zero:~$ gcc -shared -Wl,-soname,libtest.so -o libtest.so test_jni.o \
 -lpthread

zero:~$ java Main
 JNI: test_start_callback ()
 public void callback (): 0
 public void callback (): 1
 public void callback (): 2
 [...]
 public void callback (): 40
 public void callback (): 41
 public void callback (): 42

 JNI: test_stop_callback ()
zero:~$
-=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-= -=-=

What's wrong?
--