Hi,

There is at least one JNI call that is designed not to return. This is that gtkMain native method in gnu.java.awt.peer.gtk.GtkToolkit. Some VMs require all Java threads to run upto a garbage collection barrier before garbage collection can be performed. If a Java thread never leaves JNI code then this will never happen and the VM deadlocks. A solution to this is to rewrite the gtkMain loop to something like what follows:

in GtkTookit.java:

 public static void gtkMain() {
        try {
               while(true) {
                 while(gtkEventsPending()) {
                        gtkMainIteration();
                 }
                 Thread.sleep(10);
               }
        }
        catch(InterruptedException e){}
 }
 public static native void gtkMainIteration();
 private static native boolean gtkEventsPending();

in gnu_java_awt_peer_gtk_GtkToolkit.c (NB regenerate the JNI header files):

JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMainIteration
(JNIEnv *env __attribute__((unused)), jclass obj __attribute__((unused)))
{
 gdk_threads_enter ();

 gtk_main_iteration ();

 gdk_threads_leave ();
}

JNIEXPORT jboolean JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkEventsPending
(JNIEnv *env __attribute__((unused)), jclass obj __attribute__((unused)))
{
 gboolean pending;

 gdk_threads_enter ();

 pending = gtk_events_pending ();

 gdk_threads_leave ();

 return pending == TRUE ? JNI_TRUE : JNI_FALSE;
}

For performance the nested while loop could be moved into the JNI code.

Is having all JNI code return an option for classpath?

Thanks,

Ian Rogers

Reply via email to