在Mac上正确运行基于SWT的跨平台jar

我一直致力于基于SWT的项目,该项目旨在部署为Java Web Start,因此可以在多个平台上使用。

到目前为止,我已设法解决由于SWT所依赖的系统特定库所引起的导出问题(参见相关主题 )。 生成的jar似乎在32/64位linux和64位窗口上正常工作,但是在具有以下输出的Mac上执行失败:

$ java -jar dist/test.jar Adding { file:/Volumes/LaCie/ChiBE_Local/swt/swt-cocoa-macosx-x86_64-3.6.1.jar } to the classpath ***WARNING: Display must be created on main thread due to Cocoa restrictions. Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) Caused by: java.lang.ExceptionInInitializerError at org.eclipse.gef.tools.MarqueeSelectionTool.(MarqueeSelectionTool.java:99) at org.gvt.MarqueeZoomTool.(MarqueeZoomTool.java:16) at org.gvt.action.MarqueeZoomToolAction$1.(MarqueeZoomToolAction.java:28) at org.gvt.action.MarqueeZoomToolAction.createTool(MarqueeZoomToolAction.java:28) at org.gvt.action.AbstractGEFToolAction.(AbstractGEFToolAction.java:24) at org.gvt.action.MarqueeZoomToolAction.(MarqueeZoomToolAction.java:20) at org.gvt.TopMenuBar.createBarMenu(TopMenuBar.java:113) at org.gvt.ChisioMain.createMenuManager(ChisioMain.java:617) at org.eclipse.jface.window.ApplicationWindow.addMenuBar(ApplicationWindow.java:235) at org.gvt.ChisioMain.main(ChisioMain.java:149) at org.gvt.RuntimeMain.main(RuntimeMain.java:14) ... 5 more Caused by: org.eclipse.swt.SWTException: Invalid thread access at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.SWT.error(Unknown Source) at org.eclipse.swt.widgets.Display.error(Unknown Source) at org.eclipse.swt.widgets.Display.createDisplay(Unknown Source) at org.eclipse.swt.widgets.Display.create(Unknown Source) at org.eclipse.swt.graphics.Device.(Unknown Source) at org.eclipse.swt.widgets.Display.(Unknown Source) at org.eclipse.swt.widgets.Display.(Unknown Source) at org.eclipse.swt.widgets.Display.getDefault(Unknown Source) at org.eclipse.swt.widgets.Display$1.run(Unknown Source) at org.eclipse.swt.graphics.Device.getDevice(Unknown Source) at org.eclipse.swt.graphics.Resource.(Unknown Source) at org.eclipse.swt.graphics.Cursor.(Unknown Source) at org.eclipse.draw2d.Cursors.(Cursors.java:170) ... 16 more 

我检查了许多相关的主题:( 无法在Mac OS X上获得SWT显示,Mac 上的SWT问题)以及SWT常见问题解答和教程中的UI线程条目,例如将Java应用程序引入Mac和部署Mac OSX上的SWT应用程序 。

我的理解是问题源于Mac OSX上的线程处理,我应该尝试在执行时实现JVM参数-XstartOnFirstThread 。 这是正确的吗?

假设我对这个问题的理解是准确的,我有点困惑,因为这个软件旨在跨平台并在javaws上运行。 我是否需要创建一个info.plist文件,如果是这样,在包中的位置以及如何,否则如何在执行时“有条件地”将该参数传递给JVM?

提前致谢,

是的,您肯定需要-XstartOnFirstThread才能在Mac OS X上运行。由于它是一个VM参数,您只能在启动应用程序时指定它,因此从您的代码中检测操作系统并设置它,如果Mac OS X不是可能。 Eclipse网站上的解决方案创建了一个适当的Mac OS X My Application.app ,这是特定于平台的,在您的情况下再次不可行。

但是,我刚尝试在Windows XP上运行Eclipse RCP应用程序并指定了-XstartOnFirstThread参数,并且它根本没有抱怨。 这意味着您可以在JNLP文件中指定此参数,并且可能会在所有其他平台上忽略它并在Mac OS X上获取。

更新:如果由于某种原因-XstartOnFirstThread在任何平台上造成麻烦,或者您只是想做正确的事情 ,还有另一种可能的解决方案。 您可以在浏览器中检测用户的操作系统 – 假设应用程序是从网页启动的 – 并为Mac OS X和其他平台提供不同的JNLP。

更新2:正如评论中所指出的,有一个关于使用Java Web Start部署SWT应用程序的教程 。 我只是在Mac OS X(10.6.x)上启动了JNLP,它运行起来了。 看一下JNPL示例,我发现了以下内容:

    Control Example eclipse.org  A demonstration of SWT Widgets Control Example           

注意行的末尾,指向特定于平台的SWT JNLP文件 (此处省略了一些部分):

    SWT eclipse.org  SWT         ...       

它位于文件末尾:Mac OS X特定的-XstartOnFirstThread参数。

SWT(与任何其他UI框架一样)具有“UI线程”。 这通常是主线程(即执行main(String[] args)线程。所有对UI方法的调用都必须在此线程中进行。

如果需要从非UI线程调用UI方法,则必须将其包装:

 Display.getDefault().asyncExec( new Runnable() { public void run() { //ui call here } } ); 

如果您需要等待结果,可以使用syncExec()