2

I wrote small program with JavaFX, and MySQL worked through JDBC. It works well, was compiled well to jar and works from jar also well. To deliver this application to users I packed this to exe with launch4j and build custom small JRE. Exe file was created well and work, but only with full package of JRE. When I start it with my custom JRE I've got this message:

[10-Jul-2023 15:40] FATAL - DbConnection.java - Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
←[mException in Application start method
java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at javafx.graphics@19.0.2.1/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
        at javafx.graphics@19.0.2.1/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.base/java.lang.reflect.Method.invoke(Unknown Source)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method

full console text here:

As I understand the application has a problem with MySQL module (but I'm not sure). To build a custom JRE I use first jdeps:

jdeps --ignore-missing-deps --list-deps --multi-release 11 --module-path javafx\lib;libs --add-modules ALL-MODULE-PATH ExpensesViewer.jar

It shows following dependencies:

java.base
   java.datatransfer
   java.desktop
   java.logging
   java.management
   java.net.http
   java.scripting
   java.sql
   java.transaction.xa
   java.xml

   ...
   here lots of javafx modules
   ...

   jdk.jsobject
   jdk.unsupported
   jdk.unsupported.desktop
   jdk.xml.dom
   org.junit.platform.commons/org.junit.platform.commons.logging
   org.junit.platform.commons/org.junit.platform.commons.util

full list dependencies

So, I created custom JRE with jlink:

jlink --no-header-files --no-man-pages --compress=2 --strip-debug --module-path libs;javafx/lib --add-modules java.base,java.naming,java.datatransfer,java.desktop,java.logging,java.management,java.net.http,java.scripting,java.sql,java.transaction.xa,java.xml,jdk.jsobject,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom --output java-runtime

As I understand I need to add something else to modules list (because if I do not use custom but full system JRE everything works well).

And I don't understand how to find all mandatory module names that I need include (jdeps doesn't show all the necessary dependencies; for example, java.naming was mandatory, but jdeps doesn't show it).

module-info.java:

module ru.viewer.expensesviewer {
    requires javafx.controls;
    requires javafx.fxml;
    requires java.sql;
    requires mysql.connector.j;
    requires org.apache.logging.log4j;
    //requires rt;

    opens ru.viewer.expensesviewer to javafx.fxml;
    exports ru.viewer.expensesviewer;

    opens ru.viewer.expensesviewer.model to javafx.fxml;
    exports ru.viewer.expensesviewer.model;

    opens ru.viewer.expensesviewer.controller to javafx.fxml;
    exports ru.viewer.expensesviewer.controller;

    exports ru.viewer.expensesviewer.model.objects;
    opens ru.viewer.expensesviewer.model.objects to javafx.fxml;

    exports ru.viewer.expensesviewer.controller.settings;
    opens ru.viewer.expensesviewer.controller.settings to javafx.fxml;

    exports ru.viewer.expensesviewer.controller.reports;
    opens ru.viewer.expensesviewer.controller.reports to javafx.fxml;

    exports ru.viewer.expensesviewer.model.objects.settings;
    opens ru.viewer.expensesviewer.model.objects.settings to javafx.fxml;
}

added after couple hours: I tried to add all possible modules, looks like this:

jlink --no-header-files --no-man-pages --compress=2 --strip-debug --module-path libs;javafx/lib --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.management.rmi,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.se,java.security.jgss,java.security.sasl,java.smartcardio,java.sql,java.sql.rowset,java.transaction.xa,java.xml,java.xml.crypto,jdk.accessibility,jdk.attach,jdk.charsets,jdk.compiler,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.crypto.mscapi,jdk.dynalink,jdk.editpad,jdk.hotspot.agent,jdk.httpserver,jdk.incubator.foreign,jdk.incubator.vector,jdk.internal.ed,jdk.internal.jvmstat,jdk.internal.le,jdk.internal.opt,jdk.internal.vm.ci,jdk.internal.vm.compiler,jdk.internal.vm.compiler.management,jdk.jartool,jdk.javadoc,jdk.jcmd,jdk.jconsole,jdk.jdeps,jdk.jdi,jdk.jdwp.agent,jdk.jfr,jdk.jlink,jdk.jpackage,jdk.jshell,jdk.jsobject,jdk.jstatd,jdk.localedata,jdk.management,jdk.management.agent,jdk.management.jfr,jdk.naming.dns,jdk.naming.rmi,jdk.net,jdk.nio.mapmode,jdk.random,jdk.sctp,jdk.security.auth,jdk.security.jgss,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom,jdk.zipfs, --output java-runtime 

AND IT WORKS! now I exactly know that I need to discover mandatory module.

I managed find needed module with method "shot in the dark", how only I added jdk.crypto.cryptoki my custom JRE started work. But why does my program need this module? I've never use this... something for security... how should I discover this dependence?

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • 2
    `jdk.crypto.cryptoki` provides some cryptography algorithms used by some Java SSL implementations. If you used SSL or HTTPS in Java, you have probably used it without knowing so. MySQL can be connected to over SSL, which may be why you need the cryptoki module. I don’t have advice on how to determine dependency requirements for such modules. – jewelsea Jul 10 '23 at 18:57
  • 2
    My guess for why [`jdk.crypto.cryptoki`](https://docs.oracle.com/en/java/javase/20/docs/api/jdk.crypto.cryptoki/module-summary.html) didn't show up with `jdeps` is because that module is a simple service-provider for [`java.security.Provider`](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/Provider.html) and thus is not directly referenced by any code that uses it. I don't see how `jdeps` could figure out some non-modular JAR needs that specific provider and not others, considering service-providers are meant to be drop-in plugins. – Slaw Jul 10 '23 at 21:07
  • 1
    So, unfortunately, I also don't have any advice on how to determine dependencies on service-provider modules. Nor am I sure why [`java.naming`](https://docs.oracle.com/en/java/javase/20/docs/api/java.naming/module-summary.html) apparently didn't show up with `jdeps`. – Slaw Jul 10 '23 at 21:08

0 Answers0