2015-02-04 14 views
8

Powiedzmy, mamy następujące klasy:W jaki sposób JavaFX 8 uruchamia wątek aplikacji JavaFX w prawie pustej klasie aplikacji?

import javafx.application.Application; 
import javafx.stage.Stage; 

public class Test extends Application 
{ 
    public Test() 
    { 
     System.out.println("Constructor"); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception 
    { 
     System.out.println("start"); 
    } 

    public static void main(String... args) 
    { 
     System.out.println("main"); 
    } 
} 

To pochodzi od Application ale nie korzysta z żadnego z jego metod. Zwykle uruchamiasz aplikację JavaFX, dzwoniąc pod numer launch(args).

Po uruchomieniu tego programu jedynym wyjściem jest "main", więc konstruktor i start nie są wywoływane, ale program nie kończy się, ponieważ działa wątek aplikacji JavaFX. Ale skąd się bierze?

Zrobiłem kilka debugowania i okazało się, że wątek jest uruchamiany z głównego wątku przed uruchomieniem głównej metody. Śledzenie stosu rozpoczyna się od NativeMethodAccessorImpl.

Aby uzyskać jeszcze dziwniejsze: kiedy zacznę główne metody z innej klasy, nitka JavaFX aplikacji nie jest uruchomiony:

public class Test2 
{ 
    public static void main(String[] args) 
    { 
     Test.main(args); 
    } 
} 

Więc jaki rodzaj czarnej magii to jest?

+0

Awans na czarną magię. – GGrec

+0

W drugiej klasie, Test2, nie dodano rozszerzenia aplikacji w oryginalnej deklaracji klasy. Tak więc środowisko wykonawcze nie ma pojęcia, że ​​proces JavaFX jest zaangażowany - może to być główna (.) Metoda dowolnego innego rodzaju klasy Java. – Trunk

Odpowiedz

5

Java używa różnych metod uruchamiania dwóch aplikacji.

Spróbuj uruchomić następujący kod:

public class Test3 { 

    public static void main(String[] args) { 

     Class<?> actualMainClassTest = LauncherHelper.checkAndLoadMain(true, 1, Test.class.getName()); 
     Class<?> actualMainClassTest2 = LauncherHelper.checkAndLoadMain(true, 1, Test2.class.getName()); 

     System.out.println("Actual loaded main class for Test: " + actualMainClassTest.getName()); 
     System.out.println("Actual loaded main class for Test2: " + actualMainClassTest2.getName()); 
    } 
} 

wyjście jest

  • Rzeczywista załadowany Główna klasa dla Test: sun.launcher.LauncherHelper $ FXHelper
  • Rzeczywista załadowany Główna klasa dla Test2: Test2

Widać, że rzeczywista załadowana główna klasa dla Test2 klasa to Test2, ale załadowana główna klasa dla Test to sun.launcher.LauncherHelper$FXHelper.

Dzieje się tak, ponieważ program uruchamiający Java sprawdza, czy główna klasa, która ma zostać uruchomiona, jest podklasą javafx.application.Application. Jeśli tak, to ładuje główną metodę z sun.launcher.LauncherHelper$FXHelper zamiast, która wywołuje metodę wyrzutni dla aplikacji JavaFX (com.sun.javafx.application.LauncherImpl#launchApplication).

Ta metoda jest odpowiedzialna za uruchomienie aplikacji JavaFX. Test#main jest wywoływana po uruchomieniu aplikacji:

enter image description here

Kiedy Test#main jest wywoływana przez Test2, wyrzutnia FX nie jest używana, ponieważ Test2 nie jest podklasą javafx.application.Application.

+0

Tak, to zachowanie java.exe i działa tylko dla javafx.application.Application? – Rafaesp