Was macht Eclipse anders als ich?

snoopysalive

Mitglied
Hallo, zusammen!

Ich bekomme hier von Eclipse und Java gerade 'nen richtig dicken Hals, weil ich einfach nicht herausfinde, was Eclipse beim Starten einer Java-Applikation anders macht als ich. Hier mal das konkrete Problem:

Ich habe jetzt eine Woche an einer speziellen Stapelverarbeitung zur Bildmanipulation gearbeitet und nun ist dieses Java-Programm fertiggestellt.

Weil ich die grafische Programmierung mit dem SWT dem AWT und Swing vorziehe, verwende ich eben dieses, was unter Eclipse auch kein Problem darstellt: Ich gebe im Build Path einfach an, wo sich die SWT-Bibliothek befindet, und es ist gut.

Ich selber arbeite an einem Macintosh (OS X 10.5.7, Java 1.6.0_13, SWT 3.5 x86_64), das Programm soll aber auch unter Windows laufen. Also mache ich es einfach so, dass ich alle kompilierten Quelldateien in ein ausführbares JAR-File packe und im Manifest angebe, wo im Zielordner sich die SWT-Bibliothek befindet. Auf diese Weise kann ich Windows und Mac bedienen, indem ich einfach nur die Dateien im Bibliotheksverzeichnis auswechsle.

Das funktioniert soweit auch ganz gut. Das Programm ist korrekt implementiert und läuft unter Eclipse einwandfrei sowohl unter Vista als auch unter OS X. Also exportiere ich das Projekt mit Eclipses JAR-Exportier-Funktion und erhalte den besagten Ordner.

Wenn ich nun das JAR-File per Doppelklick ausführe, öffnet sich zwar noch das Hauptfenster, aber danach ist Schluss – das Programm hängt sich auf und kann nur noch extern beendet werden.

Also folgt nun im Terminal der Aufruf über java -jar. Das Programm schmiert nun wieder nach Öffnen des Hauptfensters ab, aber dieses Mal bekommt es die Möglichkeit, mir auf dem Terminal mitzuteilen, dass ein „Invalid thread access“ aufgetreten sei (eigentich gut zehn Stück).

Diese Fehler treten normalerweise nur dann unter SWT auf, wenn auf eine GUI-Komponente innerhalb eines Threads zugegriffen wird, ohne den Zugriff über Display.syncExec() bzw. Display.asyncExec() durchzuführen. Das kann aber schlicht nicht sein, weil mein Programm unter Eclipse ja noch einwandfrei gelaufen ist.

Nachdem ich aber bis jetzt noch nirgends herausfinden habe können, wie Eclipse nun genau ein Java-Programm aufruft („java -jar Programm.jar“ scheint es jedenfalls nicht zu sein, denn sonst bekäme ich ja auch unter Eclipse die besagten Fehler zu Gesicht).

Also, wie ruft Eclipse Java-Programme auf? Was kann ich tun, um mein Programm außerhalb von Eclipse zum Laufen zu bringen?

Danke,
Matthias
 
Ich habe eben noch einen Test gemacht und ein ganz kleines SWT-Programm geschrieben. Einfach nur:

Java:
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

class Test {
   private Display display;
   private Shell shell;

   public static void main(String[] args) {
      new Test();
   }

   public Test() {
      display = new Display();
      shell = new Shell(display);
      shell.setText("Test");
      shell.open();
      while (!shell.isDisposed())
         if (!display.readAndDispatch())
            display.sleep();
      shell.dispose();
   }
}

Tja, das Programm kracht bei „while (!shell.isDisposed())“ und beschwert sich über einen „Invalid Thread access“. Wenn da statt „while“ „if“ steht, geht es aber wieder. Nur ist es dann eben nicht mehr das, was man braucht.

An was kann das also liegen? Der Code funktioniert unter Eclipse schließlich tadellos. Wie kann es sein, dass er dann auf der Kommandozeile versagt, obwohl es sich hier um den Standardcode am Anfang einer jeden Eclipse-Applikation handelt?
 
Wie sieht denn deine Manifest aus?

Ich kann bei mir eines der Snippets starten wenn ich das so mache:
Code:
C:\Users\gransberger>java -cp swt.jar;SWTSnippet.jar org.eclipse.swt.snippets.Snippet294

Code:
C:\Users\gransberger>java -cp swt.jar -jar SWTSnippet.jar

Geht dagegen nicht.

Versuch mal obs mit dem oberen bei dir läuft. Mit deinem Beispiel gehts so auch bei mir.
 
Danke für den Vorschlag. Leider geht's so auch nicht. Es kommt trotzdem zum „Invalid Thread access“.

ich hab's jetzt auch nochmal mit Java 5 und der 32-Bit-Version von SWT 3.5 (welches ja noch eine Entwicklerversion ist) und der 32-Bit-Version von SWT 3.4 für Mac Carbon probiert. Bei letzterer wird zwar das Hauptfentster nun auch komplett fertig gerendert, doch dann hängt sich das Programm dennoch auf.

Wie gesagt, ich kann nicht ganz nachvollziehen, warum das Unterfangen unter Eclipse funktioniert, jedoch nicht auf der Kommandozeile. Ich hab jetzt halt schlichtweg nur wenig Lust dazu, alles nochmal neu mit Swing zu implementieren.

Weißt du oder sonst jemand zufällig, wie Eclipse die JavaVM anspricht? Ich meine, wenn Eclipse anscheindend keine Probleme mit der Chose hat, die Kommandozeile allerdings schon, dann muss Eclipse die JVM doch auf ganz spezielle Weise ansprechen, oder?
 
Meines wissens nach nicht. Der setzt auch nur den Classpath und startet dass dann so.

Nimmst du denn das selbe swt.jar in deinem eclipse drin?
 
Ja. Sprich: Ich gebe unter Eclipse im Build-Path an, wo sich die zu verwendende swt.jar befindet und dann funktioniert's. Exakt dieselbe swt.jar verwende ich dann aber auch für die Version, die ich von der Konsole aus starten möchte. Es handelt sich also wirklich immer um dieselben Dateien.
 
Hier mal noch die Fehlermeldungen von der Kommandozeile:

Code:
$ java -jar RN6ImageTool.jar 
Exception in thread "Thread-28" 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.Widget.error(Unknown Source)
	at org.eclipse.swt.widgets.Widget.checkWidget(Unknown Source)
	at org.eclipse.swt.widgets.Control.internal_new_GC(Unknown Source)
	at org.eclipse.swt.graphics.GC.cocoa_new(Unknown Source)
	at org.eclipse.swt.widgets.Control.drawWidget(Unknown Source)
	at org.eclipse.swt.widgets.Canvas.drawWidget(Unknown Source)
	at org.eclipse.swt.widgets.Widget.drawRect(Unknown Source)
	at org.eclipse.swt.widgets.Canvas.drawRect(Unknown Source)
	at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
Exception in thread "Thread-51" 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.Widget.error(Unknown Source)
	at org.eclipse.swt.widgets.Widget.checkWidget(Unknown Source)
	at org.eclipse.swt.widgets.Control.internal_new_GC(Unknown Source)
	at org.eclipse.swt.graphics.GC.cocoa_new(Unknown Source)
	at org.eclipse.swt.widgets.Control.drawWidget(Unknown Source)
	at org.eclipse.swt.widgets.Canvas.drawWidget(Unknown Source)
	at org.eclipse.swt.widgets.Widget.drawRect(Unknown Source)
	at org.eclipse.swt.widgets.Canvas.drawRect(Unknown Source)
	at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
...

Vielleicht wird daraus noch jemand schlau.

Wenn ich das Programm nicht als JAR aufrufe, sondern normal mit „java -cp bin:lib/swt/swt.jar bin/Main“ kommen exakt dieselben Fehlermeldungen.
 
Für solcherlei Probleme ist JConsole/VisualVM immer eine gute Idee. Damit kannst du dich an dein ausgeführtes Programm ranhängen und dir den exakten Aufruf inkl. aller Parameter anschauen. So könntest du z.B. mal schauen inwieweit sich der Standalonaufruf vom Aufruf über Eclipse unterscheidet.

In Java 6 sind beide Tools im bin-Verzeichnis deiner JDK Installation. Wenn du Java 5 nutzt gibt es nur JConsole und du musst, um mit JConsole an dein Progamm andocken zu können, JMX beim Programmstart deiner Applikation mit aktivieren. Das geht über einen VM Parameter, den ich grad nicht im Kopf hab, sollte in Google allerdings gut zu finden sein.

Gruß
Ollie
 
Sorry für die späte Anwort. Ich war übers Wochenende nicht da.

Danke jedenfalls für den Tipp. Das klingt schon mal mehr als brauchbar. Ich werde mich da mal einarbeiten und gucken, ob ich damit rausfinden kann, was ich falsch mache und Eclipse richtig.

Ich habe das Programm jetzt nämlich schon in Swing reimplementiert und jetzt ist es halt genau so, wie ich es nicht haben wollte. Könnte ich die SWT-Version noch irgendwie hinbekommen, wäre die mir tausendmal lieber.

Danke!
 
Wie heißt's so schön? Read the fucking manual!

Hätte ich einfach schon früher die glorreiche Idee gehabt, mal genauer auf die SWT-Homepage zu gucken, hätte ich mir eine Menge Ärger und euch eine Menge Zeit sparen können. Auf der SWT-Homepage steht lang und breit, unter OS X müsse man SWT-Programme von Konsole mit dem VM-Argument -XstartOnFirstThread starten. Tja, und schon geht's.

JConsole hatte mir ja beispielsweise nicht ausgegeben, dass Eclipse dieses Argument nutzt. Wahrscheinlich liegt es daran, dass Eclipse selbst wohl mit dieser Option gestartet wird und daher alle Prozesse, die von Eclipse gestartet werden, automatische ebenfalls diese Option erhalten, ohne dass dies extra aufgeführt wird.

Wie dem auch sei: Danke, Leute, dass ihr euch meiner angenommen habt. Fürs nächste Mal merke ich mir einfach die simpelste Sache der Welt: :google:
 

Neue Beiträge

Zurück