The Hello World-Tutorial of JavaFX says:
The main() method is not required for JavaFX applications when the JAR file for the application is created wi
One possible answer would probably be, that there is a main method declared in Application. And if another class, which extends from Application, has its own main method, the code would still be valid and the main method of Application will be ignored::
class Main extends OtherMain {
public Main(String text) {
System.out.println(text);
}
/* If this method is removed, the main-method is called from OtherMain */
public static void main(String[] args) {
new Main("Called from Main-Class");
}
}
class OtherMain {
public static void main(String[] args) {
new Main("Called from Other-Main-Class");
}
}
Does this make sense?
I've actually always been interested in how Java launches JavaFX applications, so I decided to debug the process. Some things before the rest of the answer:
Application I'm referring to the javafx.application.Application class.main method" I'm referring to the public static void main(String[] args) method. Similarly, "main class" refers to the class containing the main method.When launching a JavaFX application, if the main class is a subclass of Application then the Java launcher uses it's own, internal main class. This internal class is responsible for initializing the JavaFX toolkit. Once the toolkit is initialized, one of two things can happen.
Application subclass has a main method.
main method. It is now the developers responsibility to finish launching the application via Application.launch.Application subclass does not have a main method.
Basically, any main method declared in Application subclasses are not "normal" main methods. Think of this behavior like this:
main method acts as the entry point for the Java application—just like all "normal" main methodsApplication subclass' main method serves as an optional entry point for the JavaFX application, where the JavaFX toolkit is already initialized.First, it is not the case that you "override" the main method of the Application class; the Application class has no main method. What actually happens is that Java uses it's own main class whenever the application's declared main class is a subclass of Application. For posterity, a main class can be declared using one of the following:
java -cp <classpath> foo.Mainjava -p <modulepath> -m foo/foo.MainMain-Class: foo.MainThese steps assume a JavaFX application. Most of this doesn't happen if launching a "regular" Java application.
An internal class, LauncherHelper, checks and loads the main class via a method named checkAndLoadMain. This method is responsible for resolving the main class based on how the main class was declared (described above). Once found, this method checks whether or not the main class is a subclass of Application. If it is, then the main class is changed to a static inner class: LauncherHelper$FXHelper. Then some validation is performed and the Class is returned to, I assume, native code.
Relevant code:
main MethodAfter the main class has been found, loaded, and validated it is called from (I assume) native code. Since we are talking about a JavaFX application the main class is now LauncherHelper$FXHelper. The main method of this class does one simple thing: Invoke internal JavaFX code via reflection.
Relevant code:
The code invoked by step 2 is inside a class named LauncherImpl; specifically, the launchApplication(String,String,String[]) method. This method appears to do similar things as LauncherHelper.checkAndLoadMain except more specific to JavaFX.
I believe this method is similar to checkAndLoadMain because the checkAndLoadMain method validated the FXHelper class, which is obviously valid. However, launchApplication needs to validate the Application subclass.
Relevant code:
The next method called is launchApplicationWithArgs(ModuleAccess,String,String,String[]). This method is responsible for starting the JavaFX toolkit. After this, it loads the Application subclass and, if present, Preloader subclass as actual Class instances. It does this on the JavaFX Application Thread but then returns to the main thread.
The code then takes one of two paths depending on the presence of a main method in the Application subclass:
main method exists: Proceed to step 5.main method does not exist: Proceed to step 6 (launch the application directly)Relevant code:
main Method of Application Subclass (Optional)If there is a main method in the Application subclass it is invoked via reflection. It is now the responsibility of the developer to continue the launching procedure via a call to Application.launch. There are two overloads of the launch method:
Application.launch(String...)Application.launch(Class,String)The only difference being the first option uses the calling Class as the JavaFX Application subclass. Both end up calling LauncherImpl.launchApplication(Class,String[]). This latter method simply loads the Class of the Preloader, if needed, and then continues on to the next step.
Relevant code:
Now we're in the LauncherImpl.launchApplication(Class,Class,String[]) method. This method does two simple things:
LauncherImpl.launchApplication1(Class,Class,String[])Application.launch) in a CountDownLatch until the JavaFX toolkit exits.The launchApplication1 method will start the JavaFX toolkit if it hasn't already been started. Then it continues on to implement the standard JavaFX life-cycle. This involves creating the Application and, if present, Preloader classes then calling the init() and start(Stage) methods at the appropriate times on the appropriate threads. This life-cycle is the publicly defined behavior; virtually everything else mentioned here are implementation details.
Relevant code:
Application Main ClassThere is another way to launch JavaFX applications where the main class is not a subclass of Application, like so:
// main class
public class Main {
public static void main(String[] args) {
Application.launch(App.class, args);
}
}
// JavaFX Application class
public class App extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// setup and show primaryStage
}
}
Since Main is not a subclass of Application the change to FXHelper, in step 1, doesn't take place. This also means that steps 2-5 don't happen automatically. Instead, the call to Application.launch in Main starts this process at the final step: 6. That's why the the launchApplication1 method also tries to start the JavaFX toolkit since it wouldn't have been started in this scenario.