Using Application.launch is not the only way to start the JavaFX runtime, it's just the standard and most used option. Another option is to use Platform.startup(Runnable) (JavaFX 9+). That method will start the JavaFX runtime and invoke the given Runnable on the JavaFX Application Thread.
Platform.startup(() -> {
Stage stage = new Stage();
stage.setScene(/* your built scene */);
stage.show();
});
There are some important things to keep in mind with this setup:
The JavaFX runtime can only be started once per JVM instance; calling startup a second time will result in an IllegalStateException. If your method can be called more than once then you'll need to use Platform.runLater(Runnable) for the second and subsequent calls.
Once you close the last Stage the JavaFX runtime, by default, will exit. Once this happens you cannot start it again unless you restart the entire JVM. To stop this from happening, use Platform.setImplicitExit(false). You will now be responsible for stopping the JavaFX runtime by using Platform.exit().
Using startup bypasses the normal JavaFX lifecycle. In other words, an instance of an Application subclass won't be created and the init(), start(Stage), and stop() methods will not be invoked.
If the JavaFX portion of the application is trivial, note that the runtime will consume resources after it has been started for as long as the application exists. This is true even after you close the last window (and the implicit exit has been set to false). A (possibly non-trivial) workaround to this problem is to launch JavaFX in another process that can be destroyed as needed.
If you're using Java 9+ then another (or at least complimentary) option is to use modules. Put your Application class in a package that is only exported to the javafx.graphics module. This will prevent other modules from accessing your Application class—even if it's public.
module app {
requires javafx.graphics;
exports com.example to javafx.graphics;
}
Note: This doesn't stop people from using the classpath or using --add-exports, but that would be "using your library incorrectly" which means the behavior is unspecified.