我正在MacOSX上使用JNI编写java启动程序,以显示SplashScreen和AWT窗口。我几乎完成了程序,它成功运行JDK6,但如果显示SplashScreen,它将与JDK7一起崩溃。
整个计划是:
#include <dlfcn.h>
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <CoreServices/CoreServices.h>
typedef jint (JNICALL * FARPROC_JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
int JavaMain();
void ShowSplashWindow();
#define USEJDK6 0
int main()
{
ShowSplashWindow();
// start java in a new thread
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_JOINABLE);
pthread_t vmthread;
pthread_create(&vmthread, &thread_attr, (void *(*)(void*))JavaMain, NULL);
// start run loop
CFRunLoopSourceContext sourceContext = {
.version = 0, .info = NULL, .retain = NULL, .release = NULL,
.copyDescription = NULL, .equal = NULL, .hash = NULL,
.schedule = NULL, .cancel = NULL, .perform = NULL };
CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext);
CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);
CFRunLoopRun();
CFRelease(sourceRef);
}
// the old main to run java
int JavaMain()
{
#if USEJDK6
// load JDK with MacOSX
void * handle = dlopen("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Libraries/libserver.dylib", RTLD_LAZY);
#else
// --- or SUN JDK 1.7 ---
void * handle = dlopen("/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/server/libjvm.dylib", RTLD_LAZY);
#endif
// get JNI_CreateJavaVM
FARPROC_JNI_CreateJavaVM FN_JNI_CreateJavaVM = (FARPROC_JNI_CreateJavaVM)dlsym(handle, "JNI_CreateJavaVM");
if(FN_JNI_CreateJavaVM == NULL) FN_JNI_CreateJavaVM = (FARPROC_JNI_CreateJavaVM)dlsym(handle, "JNI_CreateJavaVM_Impl");
// Start JVM
JavaVMOption * options = new JavaVMOption[1];
memset(options, 0, sizeof(JavaVMOption) * 1);
options[0].optionString = "-Djava.class.path=.";
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
vm_args.options = options;
JavaVM * pJvm = NULL;
JNIEnv * pEnv = NULL;
int result = FN_JNI_CreateJavaVM(&pJvm, (void**)&pEnv, &vm_args);
// class
jclass clazz = pEnv->FindClass("test/HelloWorld");
if(clazz == NULL) {
pEnv->ExceptionDescribe();
pEnv->ExceptionClear();
return 1;
}
// method
jmethodID main = pEnv->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
jclass stringClass = pEnv->FindClass("java/lang/String");
jobjectArray java_argv = pEnv->NewObjectArray(0, stringClass, NULL);
pEnv->CallStaticVoidMethod(clazz, main, java_argv);
// close
pJvm->DetachCurrentThread();
pJvm->DestroyJavaVM();
return 0;
}
typedef int (*SplashLoadMemory_t)(void* pdata, int size);
typedef void (*SplashInit_t)(void);
typedef int (*SplashLoadFile_t)(const char* filename);
void ShowSplashWindow()
{
#if USEJDK6
// load JDK with MacOSX
void * handle = dlopen("/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Libraries/libsplashscreen.jnilib", RTLD_LAZY);
#else
// --- or SUN JDK 1.7 ---
void * handle = dlopen("/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/jre/lib/libsplashscreen.dylib", RTLD_LAZY);
#endif
SplashInit_t SplashInit = (SplashInit_t)dlsym(handle, "SplashInit");
SplashLoadMemory_t SplashLoadMemory = (SplashLoadMemory_t)dlsym(handle, "SplashLoadMemory");
SplashLoadFile_t SplashLoadFile = (SplashLoadFile_t)dlsym(handle, "SplashLoadFile");
SplashInit();
SplashLoadFile("test/s.jpg");
}
环境:
计划结果:
#define USEJDK6 1
使用JDK6,无论是否显示SplashScreen,程序都将成功运行。#define USEJDK6 0
使用JDK7,如果显示SplashScreen,程序将崩溃。#define USEJDK6 0
使用JDK7,如果在开头删除ShowSplashWindow();
,程序将成功运行。错误消息为SIGSEGV (0xb)
,堆栈为:
Stack: [0x00007fff56715000,0x00007fff56f15000], sp=0x00007fff56f13b80, free space=8186k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libosxapp.dylib+0x3998] +[ThreadUtilities getJNIEnv]+0x5b
C [libosxapp.dylib+0x1a77] -[NSApplicationAWT registerWithProcessManager]+0x7c
C [libosxapp.dylib+0x1493] -[NSApplicationAWT init]+0x8c
C [AppKit+0xf1864] +[NSApplication sharedApplication]+0x8f
C [libsplashscreen.dylib+0x796d] __SplashInitPlatform_block_invoke_1+0x2d
C [libdispatch.dylib+0x5f01] _dispatch_call_block_and_release+0xf
C [libdispatch.dylib+0x20b6] _dispatch_client_callout+0x8
C [libdispatch.dylib+0x70c8] _dispatch_main_queue_callback_4CF+0x113
C [CoreFoundation+0x35b4c] __CFRunLoopRun+0x66c
C [CoreFoundation+0x350e2] CFRunLoopRunSpecific+0x122
C [CoreFoundation+0x43dd1] CFRunLoopRun+0x61
C [launcherV3+0x159e] main+0xee
C [libdyld.dylib+0x27e1] start+0x0
任何人都可以帮助我如何在MacOSX上使用JDK7正确显示SplashScreen?任何人都可以指出我的程序出错了吗?
您可以在此处下载该程序:
答案 0 :(得分:3)
如果您要做的只是显示启动画面,那么通过解决方法可能会有一个更简单的答案。显然,您可以通过执行以下操作加载show a splash screen:
java -splash:filename.gif MainClass