4

When I create a Java 8 JVM in C++ I usually use something like the following code to tell JVM the class path:

JavaVMOption* options = new JavaVMOption[1];   // JVM invocation options
options[0].optionString = (char *)"-Djava.class.path=.;./lib2";   // where to find java .class
vm_args.version = JNI_VERSION_1.8;             // minimum Java version
vm_args.nOptions = 1;                          // number of options
vm_args.options = options;
vm_args.ignoreUnrecognized = false;

But how to tell the Java 9 JVM about the module path? There is no java.module.path system property. The best I can find is something like:

JavaVMOption* options = new JavaVMOption[2];   // JVM invocation options
options[0].optionString = (char *)"-Djdk.module.path=.;./lib2";   // where to find java .class
options[1].optionString = (char *)"-Djdk.module.main=RemkaAgentService";   // where to find java .class
vm_args.version = JNI_VERSION_9;             // minimum Java version
vm_args.nOptions = 2;                          // number of options
vm_args.options = options;
vm_args.ignoreUnrecognized = false;

But this code does not work, it fails when I try to create JVM. I suppose it is because it does not support the options I try.

  • shouldn't it be `java.module.path` instead of `jdk.`?(just co-relating) – Naman Apr 11 '18 at 18:33
  • Which [error code](https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#return-codes) do you get from `JNI_CreateJavaVM` ? – Jorn Vernee Apr 11 '18 at 18:49
  • 1
    JNI CreateJavaVM is for creating the VM, it doesn't load and execute the main class. For the module path, specify the option string as "--module-path=.;./lib2". Also specify "--add-modules=RemkaAgentService" to ensure that your initial module is resolved. Once the VM is created then you can use FindClass to load the main class and execute its main method. – Alan Bateman Apr 11 '18 at 19:46
  • @AlanBateman Huh, this is kind of surprisingly, since `--module-path` is not listed as a standard option here: https://docs.oracle.com/javase/9/docs/specs/jni/invocation.html#jni_createjavavm It also says: "Non-standard option names must begin with "-X" or an underscore ("_").", and java 8 rejects using `--class-path` as "Unrecognized option". – Jorn Vernee Apr 11 '18 at 20:05
  • @JornVernee, -Djdk.module.main=RemkaAgentService was wrong, if I remain only -Djdk.module.path=.;./lib2 the VM starts, but later FindClass returns nullptr. – Vitaliy Tsirkunov Apr 11 '18 at 21:02
  • Hmm, when I use that I get the warning: "Ignoring system property options whose names match the '-Djdk.module.*'. names that are reserved for internal use.". But if it works, like Alan said, you'd also need `--add-modules=RemkaAgentService` otherwise that module isn't loaded and FindClass wouldn't be able to find the class. (I can't test any more :/, even the basic example keeps seg-faulting. Taking a break for tonight) – Jorn Vernee Apr 11 '18 at 21:09
  • The name of the system property jdk.module.path I've taken from https://docs.oracle.com/javase/10/docs/api/java/lang/System.html#getProperties(). I cannot find more information about this property, so I'm not sure I'm using it right. – Vitaliy Tsirkunov Apr 11 '18 at 21:36
  • If the module packed in jar, -Djava.class.path works fine. But I've used jlink to make a distrubution smaller. – Vitaliy Tsirkunov Apr 11 '18 at 22:10
  • 2
    jdk.module.path is a read-only property, documented in an System.getProperties implNote. On the command line and JNI CreateJavaVM, the option is `--module-path`. The java/javac launchers translate `-p` to `--module-path` and also translate the space between the option and value to `=`. The initial module is tricky, the java launcher translate `-m` and `--module` to `-Djdk.module.main=`, I'd forgotten that. – Alan Bateman Apr 12 '18 at 06:23
  • @AlanBateman, I've tried: options[0].optionString = (char *)"--module-path=.;./lib2"; The JVM starts but the class is not found. if I try to add: options[1].optionString = (char *)"--module=RemkaAgentService"; JNI_CreateJavaVM returns -1. – Vitaliy Tsirkunov Apr 12 '18 at 07:26
  • To get the equivalent of the java launcher then you need to specify --module-path=... and -Djdk.module.main=... If you set _JAVA_DEBUG_LAUNCHER=1 and run the java launcher then you'll see how the options to CreateJavaVM. – Alan Bateman Apr 12 '18 at 11:12
  • @AlanBateman, I've googled about _JAVA_DEBUG_LAUNCHER=1 but could not find anything. Where have I to set it? – Vitaliy Tsirkunov Apr 12 '18 at 11:53
  • 1
    _JAVA_LAUNCHER_DEBUG is the env variable (typo in my previous comment) – Alan Bateman Apr 12 '18 at 12:56
  • I have no problem taking Math class even if there is no --module option specified. I have no problem with my class if it is in a separate jar even if it contains module-info and I do not use --module option. So, the problem I see only if my module is packed with jlink in lib/modules. Maybe my lib/modules is ignored. I've spent too much time on the problem I cannot afford to spent more. @AlanBateman, thank you for your try to help me. Later I will try to dive deep into JDK sources, but now I'm giving up. – Vitaliy Tsirkunov Apr 13 '18 at 08:51

2 Answers2

1

So the right options are the following

JavaVMOption* options = new JavaVMOption[2];   // JVM invocation options
options[0].optionString = (char *)"--module-path=.;./lib2";   // where to find java .class
options[1].optionString = (char *)"--add-modules=RemkaAgentService,spring.context";

vm_args.version = JNI_VERSION_9;             // minimum Java version
vm_args.nOptions = 2;                          // number of options
vm_args.options = options;
vm_args.ignoreUnrecognized = false;     // invalid options make the JVM init fail
  • It seems that Java11 complaints about "--module-path" and "--add-modules" arguments. This code fails when running agains Java11 – Ivan Nikitin Mar 29 '19 at 14:18
1

This is a late answer but persons that make searches about this problem may find it useful. There is indeed very few documentation to address this case, which is unfortunate. I spent some time to investigate this problem and I found a way to make it work. Here are the steps to take.

The first step removes the requirement to define the '--module-path' flag that is not supported by JNI. Note that to properly bundle your application, all you jars must be converted to modular jars. Third-party jars may not be true modular jars but rather automatic modules, but automatic modules are not supported by jlink (Using jlink with automatic modules). Fortunately, there is a method to perform this automatically documented here : creating module-info for automatic modules with jdeps in java 9

The second step works even if your class lies within a module. Notes that the class name parameter for a class 'p1.p2.p3.MyClass' must be 'p1/p2/p3/MyClass'. I mentioned this as I wasted some time due to this difference in the convention.

I may publish an example if I can find some time for this but it may not happens in a short time-frame.