I just wanted to post an update on this in case it helps some future dev
who gets stuck on the same issue.

It seems that on Mac OS you can't use JNI_CreateJavaVM() to launch the JVM
if you hope to use any GUI stuff.    This issue is described in this issue:
https://bugs.openjdk.java.net/browse/JDK-8265755

This is because the initialising the Frame class initialises the Toolkit
> class which
> in turn has to start the macos AppKit loop on this main thread of the
> application.
> This is a "hard" macOS requirement and there's no getting around it.
> So it blocks and never returns. When running a Java app in the usual way
> this
> initial thread is reserved for the UI and the thread on which the Java app
> is run
> is a different one created by the VM.
>
...

> The only workaround is not a complete workaround. So far, the appbundler
> has to use the JLI_Launch function but that function does provide any
> feedback if, say, the class loader fails.


By changing my launcher to use JLI_Launch() it resolves the simple test
case on Mac OS.  I expect that it will probably solve my other problems on
Ubuntu also.  It also comes with the added benefit of accepting arguments
at the same level of abstraction as the "java" binary itself.  E.g. When
using JNI_CreateJavaVM(), I couldn't just pass "-jar MyApplication.jar"
because it doesn't know how to parse the Main class and classpath from the
jar.   With JNI_Launch(), however, it will handle such arguments.

Here is the basic test case I built using JLI_Launch, which seems to work.
https://gist.github.com/shannah/57fc4bf4be42cac4e2ab4475f1d308a6

Anyways, thank you for all of the input you guys have provided.


Best regards

Steve


On Thu, Jan 20, 2022 at 5:00 AM Steve Hannah <st...@weblite.ca> wrote:

> Thanks for all the help on this.
>
> I have done some further digging and I think the current problem (with the
> minimal test case) may not be JavaFX specific, but rather something related
> to GUI in general on Mac OS.  I changed the test to just use Swing but it
> also hangs as soon as it tries to create a JFrame.   I'm guessing that this
> is something related to gatekeeper, or perhaps I need some special compile
> flags on MacOS to allow a binary to do GUI stuff.
>
> I find this absolutely bizarre since I had "real-world" test cases working
> earlier with almost identical code.  I must have done something in those
> real world apps that "enabled" GUI as a byproduct.  I'm just not sure what.
>
> Best regards
>
> Steve
>
> On Wed, Jan 19, 2022 at 5:04 PM Kevin Rushforth <
> kevin.rushfo...@oracle.com> wrote:
>
>> 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
>> >>
>> >
>>
>>
>
> --
> Steve Hannah
> Web Lite Solutions Corp.
>


-- 
Steve Hannah
Web Lite Solutions Corp.

Reply via email to