Utiliser correctement un bocal multi-plateforme basé sur le SWT sur un Mac

j'ai travaillé sur un projet basé sur SWT qui est destiné à être déployé comme Java Web Start, et donc être utilisé sur plusieurs plateformes.

jusqu'à présent j'ai réussi à aborder le problème d'exportation qui se pose en raison du système-spécifique bibliothèques SWT dépend de (voir thread ). La résultante jar semble démarrer correctement sur 32/64-bit linux et windows 64 bits, cependant l'exécution échoue sur un Mac avec la sortie suivante:

$ 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.<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.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

j'ai vérifié un certain nombre de threads pertinents: ( ne peut pas obtenir L'affichage SWT sur Mac OS X , problèmes avec SWT sur Mac ) ainsi que le UI Thread entry sur le SWT FAQ et des tutoriels tels que apportant votre application Java à Mac et déploiement SWT applications sur Mac OSX .

je crois comprendre que le problème vient de gestion du thread sur Mac OSX, et je devrais essayer d'implémenter l'argument JVM -XstartOnFirstThread lors de l'exécution. Est-ce exact?

en supposant que ma compréhension du problème est exacte, je suis un peu confus car ce logiciel est destiné à être multiplate-forme et fonctionne sur javaws. Est-ce que je dois créer un fichier info.plist , si oui où dans le paquet et comment, sinon comment puis-je "conditionnellement" passer cet argument à JVM au moment de l'exécution?

Merci à l'avance,

21
demandé sur Community 2010-10-20 13:21:07

2 réponses

Oui, vous aurez certainement besoin de -XstartOnFirstThread de le faire fonctionner sur Mac OS X. Puisque c'est une VM paramètre, vous ne pouvez le spécifier lors du lancement de votre application, afin de détecter le système d'exploitation à partir de votre code et de réglage si c'est Mac OS X n'est pas possible. La solution sur le site Eclipse crée un Mac OS X mon Application.app , qui est spécifique à la plate-forme et, encore une fois, pas faisable dans votre cas.

Cependant, I vient d'essayer D'exécuter une application RCP Eclipse sur Windows XP avec l'argument -XstartOnFirstThread spécifié, et il ne s'est pas plaint du tout. Cela signifie que vous pouvez spécifier cet argument dans votre fichier JNLP et qu'il sera probablement ignoré sur toutes les autres plateformes et récupéré sur Mac OS X.

mise à JOUR: Si, pour une raison quelconque, 151920920" les causes des problèmes sur toute plate-forme, ou vous voulez juste Do The Right Thing , il y a un autre solution possible. Vous pouvez détecter L'OS de l'utilisateur dans le navigateur - en supposant que l'application est lancée à partir d'une page web -, et fournir un JNLP différent pour Mac OS X et d'autres plates-formes.

mise à jour 2: comme indiqué dans les commentaires, Il ya un tutorial sur le déploiement des applications SWT avec Java Web Start . J'ai simplement lancé le JNLP sur Mac OS X (10.6.x), et cela a fonctionné. En regardant l'exemple JNPL j'ai trouvé ce qui suit:

<?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>

notez la ligne <extension href="swt.jnlp"/> vers la fin, pointant vers le fichier SWT JNLP spécifique à la plate-forme (certaines parties omises ici):

<?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>

il est là vers la fin du fichier: l'argument spécifique de Mac OS X -XstartOnFirstThread .

35
répondu Zsolt Török 2010-10-20 13:28:44

SWT (comme n'importe quel autre cadre D'UI) a un "fil D'UI". C'est généralement le fil principal (c'est-à-dire celui qui exécute main(String[] args) ). Tous les appels aux méthodes UI doivent se passer dans ce thread.

si vous devez appeler une méthode UI à partir d'un fil non-UI, vous devez l'envelopper:

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

si vous devez attendre le résultat, vous pouvez utiliser syncExec()

-3
répondu Aaron Digulla 2010-10-20 09:39:19