Подтвердить что ты не робот

Запуск SWT на основе кросс-платформенной банки на Mac

Я работал над проектом на основе SWT, который предназначен для развертывания как Java Web Start и, следовательно, будет использоваться на нескольких платформах.

До сих пор мне удалось решить проблему экспорта, которая возникает из-за системных библиотек, от SWT зависит (см. соответствующий поток). Кажется, что работающий баннер работает нормально на 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

Я проверил ряд соответствующих потоков: (Не удается получить SWT-дисплей в Mac OS X, Проблемы с SWT на Mac), а также запись в пользовательском интерфейсе в SWT FAQ и учебники, такие как Приведение вашего Java-приложения на Mac и Развертывание SWT-приложений на Mac OSX.

Насколько я понимаю, проблема связана с обработкой потоков на Mac OSX, и я должен попытаться реализовать аргумент JVM -XstartOnFirstThread при выполнении. Правильно ли это?

Предполагая, что мое понимание проблемы является точным, я немного смущен, поскольку это программное обеспечение предназначено для кросс-платформенности и запускается на javaws. Мне нужно создать файл info.plist, если да, где в пакете и как, иначе как я могу "условно" передать этот аргумент JVM во время выполнения?

Спасибо заранее,

4b9b3361

Ответ 1

Да, вам обязательно понадобится -XstartOnFirstThread, чтобы это работало в Mac OS X. Поскольку это параметр виртуальной машины, вы можете указать его только при запуске приложения, поэтому обнаруживаете ОС у вас код и устанавливаете его, если он Mac OS X невозможно. Решение на сайте Eclipse создает надлежащую Mac OS X My Application.app, которая является специфичной для платформы и, опять же, нецелесообразной в вашем случае.

Однако я просто попробовал запустить приложение Eclipse RCP в Windows XP с указанным аргументом -XstartOnFirstThread, и он вообще не жаловался. Это означает, что вы можете указать этот аргумент в своем файле JNLP и, по-видимому, он будет проигнорирован на всех других платформах и выбран на Mac OS X.

ОБНОВЛЕНИЕ: Если по какой-либо причине -XstartOnFirstThread вызывает проблемы на любой платформе или вы просто хотите сделать правильную вещь, есть еще одно возможное решение. Вы можете обнаружить пользовательскую ОС в браузере - при условии, что приложение запущено с веб-страницы - и предоставить другой JNLP для Mac OS X и других платформ.

ОБНОВЛЕНИЕ 2: Как указано в комментариях, существует учебное пособие по развертыванию приложений SWT с Java Web Start. Я просто запустил JNLP на Mac OS X (10.6.x), и он сработал. Глядя на пример 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"/> ближе к концу, указывая на специфичный для платформы SWT JNLP файл (некоторые части здесь опущены):

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

Здесь он находится к концу файла: конкретный аргумент -XstartOnFirstThread для Mac OS X.

Ответ 2

SWT (как и любая другая инфраструктура пользовательского интерфейса) имеет "поток пользовательского интерфейса". Обычно это основной поток (т.е. Тот, который выполнил main(String[] args). Все вызовы методов UI должны происходить в этом потоке.

Если вам нужно вызвать метод пользовательского интерфейса из потока, отличного от UI, вы должны его обернуть:

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

Если вам нужно подождать результата, вы можете использовать syncExec()