- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 JNI 调用一个静态 java 方法,该方法又创建一个 Swing JFrame 并显示它。代码相当简单,Java 代码独立运行(即 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,需要做什么?
--
编辑: 我插入了循环以查看哪些线程处于 Activity 状态,哪些线程不活动(可以在 this gist 中看到)。在此版本中,我在另一个线程中调用了 SwingUtilities.invokeAndWait
。结果:主线程处于 Activity 状态 (C)。 Java 派发的第一个线程(不是主线程)是存活的;执行 Call invokeAndWait
的线程被阻塞(我认为 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 的整个调用移动到一个新的 native 线程上。这适用于带有 Apples Java 32 位 (1.6.0_37) 的 Mac OS X 10.6,但会导致与上述相同的死锁。在 Mac OS X 10.8 上,情况更糟,应用程序崩溃并显示唯一消息“Trace/BPT trap: 5”(seems to be related to loading dynamic libraries)。
我还尝试按照描述捆绑二进制文件 in this Q&A ,但启动失败并显示消息 lsopenurlswithrole() failed with the message -10810
,根据 Apples Launch Services Reference,这是一个未知错误.后者也在没有尝试使用 AWT 的情况下发生(仅仅 JVM 调用失败)。
最佳答案
终于找到了解决办法。
问题不在于在哪个线程上创建虚拟机,问题在于在哪个线程上初始化 AWT 事件队列。换句话说:第一次加载 AWT 类时,它可能不会在主线程上加载。因此第 1 步:加载(例如)java.awt.Component
在另一个线程上。
但现在 EventQueue 将阻塞,因为它将工作委托(delegate)给未运行的 Cocoa Main Event Queue - 果然如此,因为它只会在主线程上运行,而主线程是我的应用程序。因此主运行循环需要在主线程上启动:
void
runCocoaMain()
{
void* clazz = objc_getClass("NSApplication");
void* app = objc_msgSend(clazz, sel_registerName("sharedApplication"));
objc_msgSend(app, sel_registerName("run"));
}
我必须将我的应用程序与 Cocoa 框架链接起来并包含 <objc/objc-runtime.h>
.主线程在调用 runCocoaMain 后被阻塞(因为事件循环在那里运行),因此需要为应用程序本身求助于另一个线程。
使用上面的代码片段运行 EventQueue 后,另一个线程上的 AWT 类加载将成功,您可以在那里继续。
关于Java JNI : Creating a Swing Window using JNI from C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14661249/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!