JNI Native Interface and JavaFX - NoClassDefFoundError

655 Views Asked by At

I have a bash script that launches my program using an embedded JRE. This script works:

#!/bin/bash
exec ./jre/bin/java \ 
   --module-path ./jre/jfx \
   --add-modules=javafx.controls,javafx.swing \
   --add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED \
   -jar  hypnos.jar "$@" --base-dir="$ROOT"

I am trying to write a C++ program that uses the JNI Native Interface to replace that bash script. As you can see, they provide identical arguments to the JVM:

#include <jni.h>  

int main() {
   JavaVM *jvm;
   JNIEnv *env;
   JavaVMInitArgs vm_args; 
   JavaVMOption* options = new JavaVMOption[4];
   options[0].optionString = (char *)"-Djava.class.path=jre/lib/server/:./hypnos.jar";
   options[1].optionString = (char *)"--module-path ./jre/jfx";
   options[2].optionString = (char *)"--add-modules=javafx.controls,javafx.swing";
   options[3].optionString = (char *)"--add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED";

   vm_args.version = JNI_VERSION_10;
   vm_args.nOptions = 1;
   vm_args.options = options;
   vm_args.ignoreUnrecognized = false;
   JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
   delete options;

   jmethodID main = NULL;
   jclass cls = NULL;

   cls = env->FindClass("net/joshuad/hypnos/Hypnos");
   if(env->ExceptionCheck()) {    
      env->ExceptionDescribe();
      env->ExceptionClear();
   }  

   if (cls != NULL) {
      main = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
   } else {
      printf("Unable to find the requested class\n");
   }  

   if (main != NULL) {
      env->CallStaticVoidMethod( cls, main, " ");
   } else {
      printf("main method not found") ;
   }

   jvm->DestroyJavaVM();
   return 0;
}

However, the bash script works while the C++ program gives me: Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application with a stack trace.

I can't understand this, because it seems that the C++ program is doing the same thing that the bash script is doing.

I have an almost-identical version of this C++ program that launches a "hello world" java program that doesn't depend on javafx, and it works. So the issue seems to be the JVM created by C++ can't find JavaFX. However, I'm pointing it all the same places that the working bash script is being pointed at, so I'm not sure why it can't find JavaFX.

Any idea how to address this?

1

There are 1 best solutions below

2
On BEST ANSWER

This

vm_args.nOptions = 1;

needs to be

vm_args.nOptions = 4;