And*_*000 6 c java macos java-native-interface swing
我是java编程的新手,所以如果这听起来像个愚蠢的问题,我会提前道歉.
我正在尝试构建一个用简单C编写的简单应用程序,它必须创建一个JavaVM然后通过加载基于Java代码创建一个新窗口AWT/Swing.
按照本技术说明,我了解到,仅在Mac OSX中,必须从与主线程不同的线程调用JavaVM,以便能够基于AWT创建GUI.
因此,在main我的C应用程序的功能中,我创建了一个新线程,它执行从创建javaVM到创建GUI的所有内容.
由于应用程序实际上并不那么简单,我将发布一个简化版本.
主功能:
int main(int argc, char** argv)
{
// Run-time loading of JavaVM framework
void *result;
result = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY);
if (!result) {
printf("can't open library JavaVM: %s\n", dlerror());
}
else {
printf("library JavaVM loaded\n");
}
/* Start the thread that runs the VM. */
pthread_t vmthread;
// create a new pthread copying the stack size of the primordial pthread
struct rlimit limit;
size_t stack_size = 0;
int rc = getrlimit(RLIMIT_STACK, &limit);
if (rc == 0) {
if (limit.rlim_cur != 0LL) {
stack_size = (size_t)limit.rlim_cur;
}
}
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (stack_size > 0) {
pthread_attr_setstacksize(&thread_attr, stack_size);
}
/* Start the thread that we will start the JVM on. */
pthread_create(&vmthread, &thread_attr, startJava, (void *)&thread_data_struct);
pthread_attr_destroy(&thread_attr);
pthread_exit(NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
线程功能:
void *startJava(void *jvm_lib)
{
JavaVMInitArgs args;
const char* classpath = getenv("CLASSPATH");
// determine classpath
char* classpath_opt = str_printf("-Djava.class.path=%s", classpath);
JavaVMOption* option = malloc(sizeof(JavaVMOption) * 2);
option[0].optionString = classpath_opt;
option[1].optionString = str_printf("-verbose:jni");
args.version = JNI_VERSION_1_6;
args.nOptions = 2;
args.options = option;
args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options
fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp = (fptr_JNI_CreateJavaVM)dl_dlsym(jvm_lib,
"JNI_CreateJavaVM");
int result = JNI_CreateJavaVM_fp(&jvm, (void**) &env, &args);
free(option);
free(classpath_opt);
// launch java code
jclass init_class = (*env)->FindClass(env, "org/classes/Loader");
jmethodID load_id = (*env)->GetStaticMethodID(env, init_class, "Load",
"(Ljava/lang/String;Lorg/classes/stuff;J)V");
(*env)->CallStaticVoidMethod(env, init_class, load_id);
}
Run Code Online (Sandbox Code Playgroud)
Java代码:(更新)
package org.classes;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Frame;
import java.awt.image.BufferedImage;
import java.awt.EventQueue;
public class Loader {
public static void Load(String baseDir, Stuff stuff, long nativePointer)
{
EventQueue.invokeLater(new Runnable() {
public void run() {
System.loadLibrary("drawingHelperLibrary");
...
...
...
// start test window
Frame frame = new Frame();
frame.setSize(640,480);
frame.setLocation(50, 50);
frame.setVisible(true);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
所有上述代码都成功执行,除了创建导致死锁或类似事件的窗口,因为终端保持忙碌而没有任何CPU使用且两个线程都保持活动状态.
如果我注释掉有关窗口创建的行,应用程序将成功执行并退出.
这是jstack的输出:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.4-b02-402 mixed mode):
"Attach Listener" daemon prio=9 tid=1040b1800 nid=0x11b888000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Low Memory Detector" daemon prio=5 tid=103806000 nid=0x10b137000 runnable [00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=9 tid=103805800 nid=0x10b034000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=9 tid=103804800 nid=0x10af31000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=9 tid=103804000 nid=0x10ae2e000 runnable [00000000]
java.lang.Thread.State: RUNNABLE
"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=103803000 nid=0x10ad2b000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=8 tid=10409b800 nid=0x10ac28000 in Object.wait() [10ac27000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f3001300> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <7f3001300> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=10409b000 nid=0x10ab25000 in Object.wait() [10ab24000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f30011d8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <7f30011d8> (a java.lang.ref.Reference$Lock)
"main" prio=5 tid=104000800 nid=0x10048d000 runnable [10048a000]
java.lang.Thread.State: RUNNABLE
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1827)
- locked <7f30010a8> (a java.util.Vector)
- locked <7f3001100> (a java.util.Vector)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1724)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
- locked <7f3004e90> (a java.lang.Runtime)
at java.lang.System.loadLibrary(System.java:1045)
at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:50)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.NativeLibLoader.loadLibraries(NativeLibLoader.java:38)
at sun.awt.DebugHelper.<clinit>(DebugHelper.java:29)
at java.awt.Component.<clinit>(Component.java:566)
at org.classes.Loader.Load(Loader.java:69)
"VM Thread" prio=9 tid=104096000 nid=0x10aa22000 runnable
"Gang worker#0 (Parallel GC Threads)" prio=9 tid=104002000 nid=0x103504000 runnable
"Gang worker#1 (Parallel GC Threads)" prio=9 tid=104002800 nid=0x103607000 runnable
"Concurrent Mark-Sweep GC Thread" prio=9 tid=10404d000 nid=0x10a6f0000 runnable
"VM Periodic Task Thread" prio=10 tid=103817800 nid=0x10b23a000 waiting on condition
"Exception Catcher Thread" prio=10 tid=104001800 nid=0x103401000 runnable
JNI global references: 913
Run Code Online (Sandbox Code Playgroud)
我真的不知道我还能做些什么.也许这是一个愚蠢的错误,但我对这种Java-C混音不够熟练,因为这是我第一次看到它.
更新:我已经更新了java代码(感谢trashgod),但它仍然无效.我错过了什么吗?
我能够通过查看Eclipse项目如何创建其启动器来解决此问题.您需要为JVM生成一个单独的线程,但主要方法需要启动CFRunLoop.
您的特定实现可能还有一些其他详细信息,但与此类似的内容目前在我们的案例中有效:
...
#include <CoreServices/CoreServices.h>
static void dummyCallback(void * info) {}
...
...
if (stack_size > 0) {
pthread_attr_setstacksize(&thread_attr, stack_size);
}
CFRunLoopRef loopRef = CFRunLoopGetCurrent();
/* Start the thread that we will start the JVM on. */
pthread_create(&vmthread, &thread_attr, startJava, (void *)&thread_data_struct);
pthread_attr_destroy(&thread_attr);
CFRunLoopSourceContext sourceContext = {
.version = 0, .info = NULL, .retain = NULL, .release = NULL,
.copyDescription = NULL, .equal = NULL, .hash = NULL,
.schedule = NULL, .cancel = NULL, .perform = &dummyCallback };
CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
CFRunLoopAddSource(loopRef, sourceRef, kCFRunLoopCommonModes);
CFRunLoopRun();
CFRelease(sourceRef);
...
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看Eclipse实现:
http://git.eclipse.org/c/equinox/rt.equinox.framework.git