Accepted answer

when running from command line, if you are choosing the maven (same works for gradle) build system, you let the plugins do the work for you.

when you run from your ide the main class, but not from the built-in maven/gradle windows, on the contrary, you are running the plain java command line options.

and these results in two different things (but with same final result of course), as you already have figured out via the properties print out.

as already covered by this answer for intellij, but applies to any other ide, or this other one for eclipse, there are two ways of running a javafx 11 project, based on the use or not of the maven/gradle build system.

javafx project, without build tools

to run your javafx project from your ide, you have to download the javafx sdk and add a library with the different javafx jars to your ide, with a path like /users/<user>/downloads/javafx-sdk-11/lib/.

now, to run that project, even if it is not modular, you have to add the path to those modules, and include the modules you are using to the vm options/arguments of the project.

whether you run the project from your ide or from command line, you will be running something like:

java --module-path /users/<user>/downloads/javafx-sdk-11/lib/ \
    --add-modules=javafx.controls org.openjfx.hellofx.hellofx

note that even if your project is not modular, you are still using the javafx modules, and since you are not using any build tool, you have to take care of downloading the sdk in the first place.

javafx project, build tools

if you use maven or gradle build tools, the first main difference is that you don't need to download the javafx sdk. you will include in your pom (or build.gradle file) what modules you need, and maven/gradle will manage to download just those modules (and dependencies) to your local .m2/.gradle repository.

when you run your main class from maven exec:java goal you are using a plugin, and the same goes for the run task on gradle.

at this point, it looks like when you run:

mvn compile exec:java


gradle run

you are not adding the above vm arguments, but the fact is that maven/gradle are taking care of it for you.


in the gradle case, this is more evident, since you have to set them in the run task:

run {
    dofirst {
        jvmargs = [
            '--module-path', classpath.aspath,
            '--add-modules', 'javafx.controls'

while you don't need the sdk, the classpath contains the path to your .m2 or .gradle repository where the javafx artifacts have been downloaded.


for maven, while the pom manages the dependencies of the different javafx modules, and sets the classifier to download the platform-specific modules (see for instance /users/<user>/.m2/repository/org/openjfx/javafx-controls/11/javafx.controls-11.pom), the plugin manages to configure the classpath and create the required options to run the project.

in short, a new class that doesn't extend application is used to call your application class: hellofx.main(args).


see this answer for a more detailed explanation on why launching a javafx application without module-path fails. but in short:

this error comes from sun.launcher.launcherhelper in the java.base module. the reason for this is that the main app extends application and has a main method. if that is the case, the launcherhelper will check for the module to be present as a named module. if that module is not present, the launch is aborted.

a more detailed explanation on how the maven plugin works without setting the module-path:

if you add debug level (default is info) when running the maven goals, you will get more detailed information on what is going on behind the scenes.

running mvn compile exec:java shows:

[debug]   (f) mainclass = org.openjfx.hellofx.hellofx
[debug] invoking : org.openjfx.hellofx.hellofx.main()

and if you check the exec-maven-plugin source code, you can find at execjavamojo::execute how the main method of the application class is called from a thread.

this is exactly what allows launching an application class from an external class that does not extend application class, to skip the checks.


is up to you to choose build tools or not, though nowadays using them is the preferred option, of course. either way, the end result will be the same.

but it is important to understand what are the differences of those approaches, and how your ide deals with them.

Related Query

More Query from same tag