我正在使用JNI调用一个静态的Java方法,该方法创建了一个Swing JFrame并显示它。代码相当简单,Java代码可以独立工作(即
我正在使用Mac OS X 10.8 Mountain Lion上的JDK 1.7.0_09。
这是我用来调用静态方法的C代码:
当我启动应用程序时,我看到
我认为我 C 进程中的虚拟机没有 AWT 事件队列,但我也不知道如何设置它来拥有一个(也不确定这是否是原因)。
为了使用 JNI 显示基于 AWT 的 GUI,需要做什么?
这也是我在StackOverflow上看到的其他问题中所读到的,例如下面评论中建议的那个。然而,我没有找到解决原始问题的方法。或许值得注意的是,在上述消息出现后,主线程仍然存活,即进程既没有死锁也没有崩溃。
我还尝试按此Q&A所述捆绑二进制文件,但启动失败,显示消息
java StartAWT
可以正常运行),但是当使用JNI从C进行调用时,进程会挂起。我正在使用Mac OS X 10.8 Mountain Lion上的JDK 1.7.0_09。
这是我用来调用静态方法的C代码:
JavaVM* jvm;
JNIEnv* env = create_vm(&jvm);
jclass class = (*env)->FindClass(env, "StartAWT");
jmethodID method = (*env)->GetStaticMethodID(env, class, "run", "()V");
(*env)->CallStaticVoidMethod(env, class, method);
(*jvm)->DestroyJavaVM(jvm);
StartAWT
类的代码如下:
public class StartAWT {
public static class Starter implements Runnable {
public void run() {
System.out.println("Runnning on AWT Queue.");
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("That's a frame!");
JLabel label = new JLabel("A Label");
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
}
}
public static class GUI implements Runnable {
public void run() {
try {
System.out.println("Going to put something on the AWT queue.");
SwingUtilities.invokeAndWait(new Starter());
} catch (Exception exc) {
throw new RuntimeException(exc);
}
}
}
public static void run() {
Thread gui = new Thread(new GUI());
gui.start();
}
}
当我启动应用程序时,我看到
Going to put something on the AWT queue
,但没有看到 Running on AWT Queue
。我认为我 C 进程中的虚拟机没有 AWT 事件队列,但我也不知道如何设置它来拥有一个(也不确定这是否是原因)。
为了使用 JNI 显示基于 AWT 的 GUI,需要做什么?
--
编辑: 我已经插入循环以查看哪些线程是活动的,哪些不是(可以在this gist中看到)。在这个版本中,我在另一个线程中调用了SwingUtilities.invokeAndWait
。结果: 主线程是活动的(C)。Java调度的第一个线程(不是主线程)是活动的; 调用invokeAndWait
的线程被阻塞(我认为甚至没有返回),应该在EventQueue上运行的函数甚至没有进入。
我还尝试直接调用SwingUtilities.invokeAndWait
,将会得到以下消息:
2013-02-02 13:50:23.629 swing[1883:707] Cocoa AWT: Apple AWT Java VM was loaded on first thread -- can't start AWT. (
0 liblwawt.dylib 0x0000000117e87ad0 JNI_OnLoad + 468
1 libjava.dylib 0x00000001026076f1 Java_java_lang_ClassLoader_00024NativeLibrary_load + 207
2 ??? 0x000000010265af90 0x0 + 4335185808
)
这也是我在StackOverflow上看到的其他问题中所读到的,例如下面评论中建议的那个。然而,我没有找到解决原始问题的方法。或许值得注意的是,在上述消息出现后,主线程仍然存活,即进程既没有死锁也没有崩溃。
--
编辑:我在Linux上测试了该代码,结果符合预期。因此,我认为这是与Cocoa AWT有关的Mac OS X问题,但我不知道如何规避它。
--
编辑:我还尝试将整个JVM的调用移动到一个新的本地线程上。这在Mac OS X 10.6上使用苹果Java 32位(1.6.0_37)可以工作,但会导致与上述相同的死锁。在Mac OS X 10.8上更糟糕,应用程序会崩溃,并显示唯一的消息“Trace/BPT trap: 5”(这似乎与加载动态库有关)。我还尝试按此Q&A所述捆绑二进制文件,但启动失败,显示消息
lsopenurlswithrole() failed with the message -10810
,这是一个未知错误,根据苹果的Launch Services Reference。后者即使不尝试使用AWT也会发生(仅JVM调用失败)。
JavaApplicationStub
,但我不知道它是如何工作的。我想知道在这里引用的JVM TI
是否有任何相关内容。 - trashgod