我一直致力于基于SWT的项目,该项目旨在部署为Java Web Start,因此可以在多个平台上使用。
到目前为止,我已设法解决由于SWT所依赖的系统特定库而导致的导出问题(参见相关thread)。生成的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.<init>(MarqueeSelectionTool.java:99)
at org.gvt.MarqueeZoomTool.<init>(MarqueeZoomTool.java:16)
at org.gvt.action.MarqueeZoomToolAction$1.<init>(MarqueeZoomToolAction.java:28)
at org.gvt.action.MarqueeZoomToolAction.createTool(MarqueeZoomToolAction.java:28)
at org.gvt.action.AbstractGEFToolAction.<init>(AbstractGEFToolAction.java:24)
at org.gvt.action.MarqueeZoomToolAction.<init>(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.<init>(Unknown Source)
at org.eclipse.swt.widgets.Display.<init>(Unknown Source)
at org.eclipse.swt.widgets.Display.<init>(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.<init>(Unknown Source)
at org.eclipse.swt.graphics.Cursor.<init>(Unknown Source)
at org.eclipse.draw2d.Cursors.<clinit>(Cursors.java:170)
... 16 more
我检查了许多相关主题:(Can't get SWT Display on Mac OS X,Problems With SWT on Mac)以及UI Thread entry on the SWT FAQ和教程,例如Bringing your Java App to Mac和Deploying SWT applications on Mac OSX。
我的理解是问题源于Mac OSX上的线程处理,我应该尝试在执行时实现JVM参数-XstartOnFirstThread
。这是对的吗?
假设我对这个问题的理解是准确的,我有点困惑,因为这个软件旨在跨平台并在javaws上运行。我是否需要创建一个info.plist
文件,如果是这样,在包中的位置以及如何,否则如何在执行时“有条件地”将该参数传递给JVM?
提前致谢,
答案 0 :(得分:36)
是的,您肯定需要-XstartOnFirstThread
才能在Mac OS X上使用它。由于它是一个VM参数,您只能在启动应用程序时指定它,因此从您的代码中检测操作系统并设置它它是Mac OS X是不可能的。 solution on the Eclipse site创建了一个合适的Mac OS X 我的Application.app ,这是特定于平台的,在您的情况下再次不可行。
但是,我刚尝试在Windows XP上运行Eclipse RCP应用程序并指定了-XstartOnFirstThread
参数,并且它根本没有抱怨。这意味着您可以在JNLP文件中指定此参数,并且可能会在所有其他平台上忽略它并在Mac OS X上获取。
更新:如果出于某种原因-XstartOnFirstThread
导致任何平台出现问题,或者您只想做正确的事,还有另一种可能的解决方案。您可以在浏览器中检测用户的操作系统 - 假设应用程序是从网页启动的 - 并为Mac OS X和其他平台提供不同的JNLP。
更新2:正如评论中指出的那样,有一个tutorial on deploying SWT applications with Java Web Start。我只是在Mac OS X(10.6.x)上启动了JNLP,它运行起来了。看example JNPL我发现了以下内容:
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+"
codebase="http://www.eclipse.org/swt/jws/"
href="controlexample.jnlp">
<information>
<title>Control Example</title>
<vendor>eclipse.org</vendor>
<homepage href="http://www.eclipse.org/swt/jws/" />
<description>A demonstration of SWT Widgets</description>
<description>Control Example</description>
</information>
<security>
<all-permissions />
</security>
<resources>
<extension href="swt.jnlp"/>
<jar href="controlexample.jar" />
</resources>
<application-desc main-class="org.eclipse.swt.examples.controlexample.ControlExample" />
</jnlp>
注意最后的<extension href="swt.jnlp"/>
行,指向platform-specific SWT JNLP file(此处省略了部分内容):
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+"
codebase="http://www.eclipse.org/swt/jws/"
href="swt.jnlp">
<information>
<title>SWT</title>
<vendor>eclipse.org</vendor>
<homepage href="http://www.eclipse.org/swt/jws/" />
<description>SWT</description>
</information>
<security>
<all-permissions />
</security>
<resources os="Windows" arch="x86">
<j2se version="1.4+" />
<jar href="swt-win32-windows-x86.jar" />
</resources>
...
<resources os="Mac\ OS\ X">
<j2se version="1.5*" java-vm-args="-XstartOnFirstThread"/>
<jar href="swt-carbon-osx-universal.jar" />
</resources>
<component-desc/>
</jnlp>
它位于文件的末尾:Mac OS X特定的-XstartOnFirstThread
参数。
答案 1 :(得分:-3)
SWT(与任何其他UI框架一样)具有“UI线程”。这通常是主线程(即执行main(String[] args)
的线程。所有对UI方法的调用都必须在此线程中进行。
如果需要从非UI线程调用UI方法,则必须将其包装起来:
Display.getDefault().asyncExec( new Runnable() {
public void run() {
//ui call here
}
} );
如果您需要等待结果,可以使用syncExec()