Point #1 is one of the known limitations of using javafx modules on the classpath (and is one of the reasons we recommend against it), so that's not surprising. And I see you found the workaround.

I wonder if it might have something to do with a shared library that is being loaded in one case and not the other, but that's just a vague guess. Maybe someone else will spot something.

Since you have something minimal that reproduces the problem for you, can you file a bug?

-- Kevin


On 1/19/2022 4:07 PM, Steve Hannah wrote:
I've reduced the problem down to something minimal and have found that:

1. If your main class extends Application, and you try to run it like:
java -jar MyApplication.jar

It will fail immediately with:
Error: JavaFX runtime components are missing, and are required to run this
application

2. If you "trick" it, by making your Application class a separate class
that you call from your main class, it will run fine using:
java -jar MyApplication.jar

3. It will also run fine in this scenario using
-Djava.class.path=MyApplication.jar instead of -jar:
java -Djava.class.path=MyApplication.jar Main

3. If I try to simulate the exact same thing with my own launcher, it will
hang somewhere in the JavaFX initialization:

with javafx.verbose=true, the output is:

System.loadLibrary(prism_es2) succeeded
JavaFX: using com.sun.javafx.tk.quantum.QuantumToolkit
System.loadLibrary(glass) succeeded

But it hangs there, and never displays the screen.

The C code for this launcher is:

char *mainClass;

JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[2];
mainClass = "Main";
options[0].optionString = "-Djava.class.path=MyApplication.jar";
options[1].optionString = "-Djavafx.verbose=true";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 2;
vm_args.ignoreUnrecognized = 0;

jobjectArray args;
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
if (res < 0) {
     printf("Can't create Java VM\n");
     exit(1);
}
jclass cls = (*env)->FindClass(env, mainClass);
if (cls == 0) {

     printf("Main class %s class not found\n", mainClass);
     exit(1);
}
jmethodID mid =
(*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
if (mid == 0) {
     printf("main() method not found\n");
     exit(1);
}
//jstring argString = (*env)->NewStringUTF(env, ""); //empty arg list
args =
  (*env)->NewObjectArray(env, 0, (*env)->FindClass(env,
"java/lang/String"), NULL);
if (args == 0) {
     printf("Out of memory\n");
     exit(1);
}

(*env)->CallStaticVoidMethod(env, cls, mid, args);



Can anyone spot any differences between that and running with the "java"
binary:?
java -Djava.class.path=MyApplication.jar Main

I have experimented both with JDKs that include JavaFX (e.g. Zulu) and ones
that do not (e.g. AdoptOpenJDK).  Both exhibit the same behaviour (except
with AdoptOpenJDK, I also add the javafx jars to the classpath).

For this test I'm using JDK 11 on Mac OS Mojave, but it is consistent with
my earlier troubles on Ubuntu (also JDK11).


Best regards

Steve


On Wed, Jan 19, 2022 at 3:06 PM John Neffenger <j...@status6.com> wrote:

On 1/19/22 2:12 PM, Steve Hannah wrote:
I have been resisting using modules for a long time because it just makes
things more complicated, ...
It also makes some things easier, though, and certainly smaller. It's
easier to use an old-school Makefile with modules, and using 'jlink' can
get a simple Hello World JavaFX application and Java runtime down to
just 31 megabytes.

Here's my minimal, no-magic example:

https://github.com/jgneff/hello-javafx

with a simple Makefile:

https://github.com/jgneff/hello-javafx/blob/main/Makefile

and a Maven POM for use online with Maven Central or offline with a
local Debian- or Ubuntu-built Maven repository:

https://github.com/jgneff/hello-javafx/blob/main/pom.xml

John



Reply via email to