2009-10-14 30 views
6

Sono in esecuzione Mac OS X Snow Leopard e non è possibile accedere al display dall'attivatore in un pacchetto OSGi.Impossibile visualizzare SWT su Mac OS X

Di seguito si riporta il metodo di inizio per la mia attivatore:

@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(); 
     } 
    }); 
} 

si chiama questo codice in un ambiente di Windows funziona bene, ma la distribuzione su Mac OS XI ottenere il seguente risultato:

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

I' Ho usato l'argomento -XstartOnFirstThread VM senza fortuna. Sono su Cocoa 64-bit ma ho anche provato Cocoa a 32-bit.

Quando si cerca il carbonio ottengo il seguente errore:

 
Invalid memory access of location 00000020 eip=9c 

Quando il debug nella classe di visualizzazione posso vedere che l'array Displays [] contiene solo riferimenti nulli.

+0

Funziona in Windows? Veramente? Dovrò provare quello ... – andyczerwonka

risposta

2

Posso confermare che abbiamo eseguito con successo SWT Carbon su Mac OS X nel proprio ciclo di eventi avviato da un'attivazione di pacchetto, quindi è sicuramente possibile! Questo sta usando -XstartOnFirstThread all'avvio della VM.

Ma, con cacao SWT (64-bit), vedo lo stesso errore :(

Sembra che, anche se il modo in cui abbiamo corso Carbon SWT funzionava, era probabilmente non kosher: stavamo guidando il ciclo degli eventi passa attraverso un altro thread, non quello principale come si suppone .. Sotto Cocoa SWT, questo non funziona più, ed è stata probabilmente pratica dubbia comunque

Posso correggere gli errori del pool di thread con il seguente hack prima di creare il display (adattato dal costruttore del dispositivo SWT Cocoa):

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(); 
    } 

Tuttavia, il loop di eventi che segue si blocca (es. the display.readAndDispatch() /display.sleep() dance). Sospetto che non stia leggendo gli eventi dell'interfaccia utente perché non è il thread principale.

Non sono sicuro se c'è un modo kosher per risolvere questo problema. Nel mio caso, controlliamo il thread JVM principale che avvia OSGi, quindi mi viene in mente l'idea di aggiungere un hook che possa eseguire il ciclo di eventi SWT dopo il lancio di OSGi.

+0

È possibile ottenere qualche codice semplice per farlo funzionare? E una configurazione di avvio di lavoro? –

+0

Hai capito bene la mia domanda. L'ultimo commento che stai dicendo è che stai cercando di aggiungere un hook per eseguire il ciclo di eventi SWT. Credo che sia supportato dalla classe Display, una volta creata la prima istanza nel thread principale, i metodi statici funzioneranno come previsto. Almeno se credi ai documenti. Da quanto ho capito, sarai in grado di chiamare Display.asyncExec (..) per eseguire il codice nel thread dell'evento SWT ... è così che lo fai in Eclipse almeno. –

+0

La creazione dell'istanza di visualizzazione nel thread principale è la parte difficile! Usiamo una generica classe "bootstrap" che lancia il framework OSGi, e non ha idea di SWT o nemmeno dell'accesso alle classi poiché sono effettivamente caricate in seguito dal bundle SWT. La mia idea è di aggiungere una sorta di hook generico al codice bootstrap, che verrà utilizzato dal bundle SWT per ottenere il loop eseguito dal thread principale. Il trucco è farlo in modo pulito ... –

0

Questo codice sembra molto strano ... questo dovrebbe essere un plugin Eclipse? Cosa stai cercando di fare? Immagino che tu stia cercando di creare un plugin RCP con un'interfaccia utente. Se è così, ecco la risposta: non farlo. OSGi Activator non è responsabile della creazione del ciclo degli eventi di visualizzazione SWT.

Creare un'estensione di applicazione nel file plugin.xml per creare in modo dichiarativo il bootstrap SWT. Sarà simile a questa:

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

quindi creare la classe Application (chiamatelo come volete) per cercare qualcosa di simile:

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(); 
      } 
     }); 
    } 
} 

Ovviamente assicurarsi di avere i plugin SWT (org. eclipse.ui) disponibile nel tuo Manifesto e anche nel runtime.

Spero che questo aiuti.

+1

No Non sto cercando di creare un plugin Eclipse. Sto cercando di utilizzare SWT in un ambiente OSGi senza Eclipse RCP. So che il Workbench in RCP è responsabile della creazione del display e che viene eseguito nel thread principale prima che vengano attivati ​​tutti i plug-in. AFAIK dovrebbe essere possibile creare la visualizzazione in qualsiasi thread, purché venga utilizzato come thread dell'interfaccia utente. Dalla doc: "In SWT, il thread che crea un'istanza di visualizzazione si distingue come il thread dell'interfaccia utente per tale visualizzazione." –

+0

Tuttavia, ho appreso che Mac OS X richiede che thread sia thread 0. Ciò potrebbe spiegare perché funziona su Windows ma non su Mac. Non so come risolverlo però ... –

+0

Vuoi SWT senza RCP ma vuoi OSGi - sembra strano. RCP è fondamentalmente SWT e OSGi con alcuni altri plugin che non devi usare se non li vuoi. – andyczerwonka

1

Ho avuto il problema che non appena è stato chiamato "display.sleep()", la finestra ha bloccato l'applicazione. Se qualcun altro ha lo stesso problema, la soluzione che ha funzionato per me è stata aggiungere: -XstartOnFirstThread alla VM al momento dell'esecuzione.

Stavo cercando di far funzionare il software Areca Backup sul mio Mac, e so il suo funzionamento :)

Il mio sistema è: MacOsX Snow Leopard 10.6.2

Bye, Daniel W.

1

Ho avuto lo stesso problema e l'ho risolto aggiungendo sia -d32 e -XstartOnFirstThread