无法在Mac OS X上获得SWT显示

时间:2009-10-14 15:38:50

标签: swt osgi eclipse-rcp

我正在运行Mac OS X Snow Leopard并且不想从OSGi包中的激活器访问显示器。

以下是我的激活器的启动方法:

@Override
public void start(BundleContext context) throws Exception {
    ExecutorService service = Executors.newSingleThreadExecutor();
    service.execute(new Runnable() {

        @Override
        public void run() {
            Display display = Display.getDefault();
            Shell shell = new Shell(display);
            Text helloText = new Text(shell, SWT.CENTER);
            helloText.setText("Hello SWT!");
            helloText.pack();
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }
            display.dispose();
        }
    });
}

在Windows环境中调用此代码可以正常工作,但在Mac OS X上部署我得到以下输出:

2009-10-14 17:17:54.050 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x101620d20 of class NSCFString autoreleased with no pool in place - just leaking
2009-10-14 17:17:54.081 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x100119240 of class NSCFNumber autoreleased with no pool in place - just leaking
2009-10-14 17:17:54.084 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x1001024b0 of class NSCFString autoreleased with no pool in place - just leaking
2009-10-14 17:17:54.086 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x7fff701d7f70 of class NSCFString autoreleased with no pool in place - just leaking
2009-10-14 17:17:54.087 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x100113330 of class NSCFString autoreleased with no pool in place - just leaking
2009-10-14 17:17:54.092 java[2010:10003] *** __NSAutoreleaseNoPool(): Object 0x101624540 of class NSCFData autoreleased with no pool in place - just leaking
.
.
.

我没有运气就使用了-XstartOnFirstThread VM参数。我使用的是64位Cocoa,但我也尝试过使用32位Cocoa。

尝试使用Carbon时出现以下错误:

Invalid memory access of location 00000020 eip=9012337c

调试Display类时,我可以看到Displays []数组只包含空引用。

4 个答案:

答案 0 :(得分:2)

我可以确认我们已经在Mac OS X上成功运行了SWT Carbon ,它在自己的事件循环中通过捆绑激活启动,所以这绝对是可能的!这是在启动VM时使用-XstartOnFirstThread。

但是,使用Cocoa SWT(64位),我看到同样的错误:(

似乎虽然我们运行Carbon SWT的方式有效,但它可能不是犹太人:我们通过另一个线程驱动事件循环,而不是你想要的那个主线程。在Cocoa SWT下,这不再适用了,无论如何它可能都是狡猾的练习。

我可以在创建Display之前使用以下hack修复线程池错误(改编自Cocoa SWT Device构造函数):

  NSAutoreleasePool pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
  NSThread nsthread = NSThread.currentThread();
  NSMutableDictionary dictionary = nsthread.threadDictionary();
  NSString key = NSString.stringWith("SWT_NSAutoreleasePool");
  id obj = dictionary.objectForKey(key);
  if (obj == null) {
          NSNumber nsnumber = NSNumber.numberWithInteger(pool.id);
          dictionary.setObject(nsnumber, key);
  } else {
          pool.release();
  }

但是,后面的事件循环会挂起(即display.readAndDispatch()/ display.sleep()dance)。我怀疑它不是因为不是主线程而读取UI事件。

我不确定是否有一种犹太方法来解决这个问题。在我的例子中,我们控制启动OSGi的主要JVM线程,因此我想在OSGi启动后添加一个可以运行SWT事件循环的钩子。

答案 1 :(得分:1)

我遇到的问题是,只要“display.sleep()”被调用,窗口就会冻结应用程序。如果其他人遇到同样的问题,那对我有用的解决方案就是添加: -XstartOnFirstThread 执行时到VM。

我试图让Areca Backup软件在我的Mac上运行,并且知道它正在工作:)

我的系统是:MacOsX Snow Leopard 10.6.2

再见 丹尼尔W。

答案 2 :(得分:1)

我遇到了同样的问题,并通过添加-d32-XstartOnFirstThread

解决了这个问题

答案 3 :(得分:0)

这段代码看起来很奇怪......这应该是一个Eclipse插件吗?你想做什么?我猜你正在尝试使用用户界面创建一个RCP插件。如果是这样,这就是答案:不要那样做。您的OSGi Activator不负责创建SWT显示事件循环。

在plugin.xml中创建一个应用程序扩展,以声明方式创建SWT引导程序。它看起来像这样:

   <extension
         id="application"
         point="org.eclipse.core.runtime.applications">
      <application>
         <run
               class="com.yourcompany.foo.Application">
         </run>
      </application>
   </extension>

然后创建Application类(随意调用它),看起来像这样:

public class Application implements IApplication {

    /* (non-Javadoc)
     * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
     */
    public Object start(IApplicationContext context) {
        Display display = PlatformUI.createDisplay();
        try {
            int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
            if (returnCode == PlatformUI.RETURN_RESTART) {
                return IApplication.EXIT_RESTART;
            }
            return IApplication.EXIT_OK;
        } finally {
            display.dispose();
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.equinox.app.IApplication#stop()
     */
    public void stop() {
        final IWorkbench workbench = PlatformUI.getWorkbench();
        if (workbench == null)
            return;
        final Display display = workbench.getDisplay();
        display.syncExec(new Runnable() {
            public void run() {
                if (!display.isDisposed())
                    workbench.close();
            }
        });
    }
}

显然要确保你的Manifest和运行时都有SWT插件(org.eclipse.ui)。

我希望有所帮助。