即使在vm args中使用XstartOnFirstThread也无效的线程访问

Pet*_*ter 4 java macos java-web-start

我有一个胚胎Java Web Start应用程序,只有一个类.它在Windows和Linux上运行,但在Mac OS X上遇到了可怕的无效线程访问错误.我意识到这已在其他地方处理过.我花了整整两天时间在互联网上搜索并实施了所有解决方案,但问题仍然存在.

我的理解是,必须从主线程调用SWT,这就是这里的情况.如果我错了,请纠正我.

我将在下面发布3个片段,应用程序的源代码,jnlp文件的相关部分以及Mac上的错误消息.问题是最后的问题.


JAVA SOURCE CODE

package client;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class AccountWindow {
 public static void main(String[] args) {
  Display display = new Display(); **// error occurs here**
  Shell shell = new Shell(display); shell.open();
  while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
    display.sleep();
  }
  display.dispose();
 }
}
Run Code Online (Sandbox Code Playgroud)

JNLP SNIPPET

<resources os="Mac\ OS\ X" arch="x86_64">
    <j2se version="1.5+" java-vm-args="-XstartOnFirstThread" />
    <nativelib href="swt-4.2-cocoa-macosx-x86_64.jar" />
</resources>
Run Code Online (Sandbox Code Playgroud)

错误信息

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 client.AccountWindow.main(AccountWindow.java:16)
    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 com.sun.javaws.Launcher.executeApplication(Launcher.java:1550)
    at com.sun.javaws.Launcher.executeMainClass(Launcher.java:1488)
    at com.sun.javaws.Launcher.doLaunchApp(Launcher.java:1299)
    at com.sun.javaws.Launcher.run(Launcher.java:114)
    at java.lang.Thread.run(Thread.java:637)
Run Code Online (Sandbox Code Playgroud)

请注意
- 发布在http://www.eclipse.org/swt/faq.php#javawebstart上的display.syncExec解决方案不适用,因为在您调用它之前,您需要显示.当我尝试创建显示时,会发生错误.
- 我使用JaNeLa验证jnlp文件,没有红色错误.
- <resources os ="Mac\OS\X"arch ="i386">正在被正确解释,因为正在加载正确的swt库.
- 您可以在http://thelinkjuicer.com/gannonline/client.jnlp上重现错误


现在问题
任何人都可以在源代码或jnlp片段中看到任何会导致错误的内容吗?
次要问题:如何判断VM是否实际读取了-XstartOnFirstThread参数?

Mar*_*nik 5

显然,主要方法没有在主线程上执行.您可以在堆栈跟踪中看到启动器实际上是在另一个线程中启动的,然后是Launcher唯一的间接调用main.不幸的是,这只是诊断,我不确定解决方案.我做了类似的事情(通过Java Web Start的SWT应用程序),但我不记得我们是如何解决这个问题的,如果有的话.

在检查com.sun.javaws.Launcher源代码之后,目前还不清楚如何使其工作.该Launcher.launch方法启动一个新线程,在该线程中main执行您的方法.您可以按照代码重新创建您正在获得的精确堆栈跟踪.

Java Web Start 的主要入口点表明主线程在启动后很快就会死掉.

更新

我挖了一些东西:在这个Eclipse bug报告中,建议问题可能与此有关:

<resources>
  <j2se version="1.4+" />
  <jar href="client.jar" />
</resources>
Run Code Online (Sandbox Code Playgroud)

解析器从这里获取j2se规范并忽略后面更具体的规范.尝试删除该<j2se...行.

更新2

现在我从这里挖出:

com.apple.concurrent.Dispatch.getInstance().getNonBlockingMainQueueExecutor().execute(
  new Runnable() { public void run() {
      final Display display = Display.getDefault(); 
      while (!display.isDisposed()) {
        if (!display.readAndDispatch())
          display.sleep();
      }
});
Run Code Online (Sandbox Code Playgroud)

这实际上听起来像是可行的.它完全按照我在下面的评论中描述的那样:通过专门为此目的而实施的机制修补主线程.尝试根据您的需要进行调整.您可能甚至不需要-XstartOnFirstThread.

更新3

我终于找到了我的旧SWT-JWS项目.它有这个:

<resources os="Mac OS X" arch="x86_64">
  <j2se version="1.6+" java-vm-args="-XstartOnFirstThread"/>
  <jar href="swt-cocoa-macosx-x86-64-3.6.2.jar" />
</resources>
Run Code Online (Sandbox Code Playgroud)

它的工作原理.它没有默认j2se元素,此元素出现在OSX特定的条目中.