8

I am trying to reduce the size of my application by limiting the modules that it includes. I already did this for my runtime using jlink. However, when I run javapackager using the --add-modules and --limit-modules options with a comma-separated list of the same small set of modules I used for the runtime, it insists on adding all of the modules anyway. It doesn't seem to want to honor the option I'm giving it. How can I get the tool to limit the modules it adds to my app bundle?

"Adding modules: [java.base, java.desktop, java.naming, java.sql, java.xml, java.logging, 
    java.management, java.scripting, java.compiler, java.rmi, java.activation, jdk.charsets, jdk.xml.dom, 
    java.datatransfer, jdk.httpserver, javafx.base, java.security.sasl, jdk.zipfs, jdk.crypto.ec, 
    jdk.management.agent, java.sql.rowset, javafx.swing, jdk.jsobject, jdk.sctp, java.smartcardio, 
    jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, javafx.graphics, javafx.fxml, jdk.dynalink, 
    javafx.media, jdk.accessibility, jdk.security.jgss, javafx.web, java.xml.crypto, jdk.jfr, jdk.packager.services, jdk.net, javafx.controls, 
    java.prefs, jdk.naming.rmi, jdk.jdwp.agent, java.instrument, jdk.management, 
    jdk.security.auth, java.management.rmi, jdk.naming.dns, jdk.localedata] to runtime image."
outputDir = ...
modulePath = [/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/jmods]
addModules = [java.base, java.desktop, java.naming, java.sql, java.xml, java.logging, java.management, java.scripting, java.compiler, java.rmi, java.activation, jdk.charsets, 
    jdk.xml.dom, java.datatransfer, jdk.httpserver, javafx.base, java.security.sasl, jdk.zipfs, jdk.crypto.ec, jdk.management.agent, java.sql.rowset, javafx.swing, jdk.jsobject, 
    jdk.sctp, java.smartcardio, jdk.unsupported, jdk.scripting.nashorn, java.security.jgss, javafx.graphics, javafx.fxml, jdk.dynalink, javafx.media, jdk.accessibility, jdk.security.jgss, javafx.web, java.xml.crypto, jdk.jfr, 
    jdk.packager.services, jdk.net, javafx.controls, java.prefs, jdk.naming.rmi, jdk.jdwp.agent, java.instrument, jdk.management, jdk.security.auth, java.management.rmi, jdk.naming.dns, jdk.localedata]
limitModules = [java.base, java.desktop, java.naming, java.sql, java.xml, java.logging, java.management, java.scripting, java.compiler, java.rmi, java.activation]

Here is the command that I run, with some things like username replaced:

/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/javapackager -deploy -native image \
-name Commander -title Commander -vendor "username" \
-appclass com.username.commander.ui.AppWindow \
-srcdir /Users/username/Dropbox/coding/commander/Commander-java/packageJars \
-outdir /Users/username/Dropbox/coding/commander/Commander-java/target \
-outfile Commander \
-Bruntime=target/jre-9.0.1 -Bicon=src/main/resources/icons/commander.icns \
-BappVersion=1.0 \
-Bmac.CFBundleIdentifier=com.username.Commander \
-BmainJar=commander-0.0.1-SNAPSHOT-jar-with-dependencies.jar \
--add-modules java.base,java.desktop,java.naming,java.sql,java.xml,java.logging,java.management,java.scripting,java.compiler,java.rmi,java.activation \
--limit-modules java.base,java.desktop,java.naming,java.sql,java.xml,java.logging,java.management,java.scripting,java.compiler,java.rmi,java.activation \
-nosign -v
GabeV
  • 859
  • 8
  • 21
  • What if you specify `-BmainJar=commander-0.0.1-SNAPSHOT-jar-with-dependencies.jar ` as `-srcfiles commander-0.0.1-SNAPSHOT-jar-with-dependencies.jar` instead? – Naman Oct 23 '17 at 05:16
  • Heh, I tried that and it gives me another error that `srcfiles` cannot contain module-info files. That has prompted another question which you're also aware of :) – GabeV Oct 23 '17 at 05:23

2 Answers2

6

So it turns out that the reason why it wasn't honoring my options is because my app jar is not a Java 9 module. It's a plain old jar. In Java 9, javapackager uses jlink to generate the runtime and will not try to limit the number of modules because it can't determine the module dependencies. The -Bruntime option is only for Java Web Start applications. If you want javapackager to not use jlink, you have to use the one in JDK 8.

I cannot turn my app jar into a module due to the complexity involved with all the 3rd party dependencies (you can see the details in this question). And I can't use JDK 8 because I need some APIs added to the Desktop module in Java 9. So, I found a workaround to get a slimmer runtime into the app using the Java 9 javapackager:

  1. Generate a slimmer runtime using jlink by specifying only the modules that you need using the --add-modules option. You can use the jdeps command to figure out which modules are needed by all the jars in your app.
  2. Generate the .app with the full runtime using javapackger as usual.
  3. Open up your generated .app file (macOS) or for Windows, use something that will let you edit the .exe or .msi installer (don't know how to do this myself).
  4. On macOS, replace the contents of <myApp>.app/Contents/PlugIns/Java.runtime/Contents/Home with those of your slimmer runtime. Do something similar for the Windows installer.
GabeV
  • 859
  • 8
  • 21
2

Using the command line javapackager, you can make use of the deploy options --limit-modules and --add-modules such as:-

javapackager -deploy 
    --add-modules java.base,java.desktop... 
    --limit-modules java.base,java.desktop,java.naming...
    --module-path your.mods.dir
    -native -outdir OUTPUT_DIR -outfile APPLICATION_NAME 
    -srcdir PACKAGE_SRC_DIR -srcfiles APPLICATION.jar -appclass MAIN_CLASS
    -name "YourApplication" -title "SelfContained"

Or colloquially a deploy ant task would consist of something like:-

<fx:runtime strip-native-commands="false">
    <fx:add-modules value="java.base"/>
    <fx:add-modules value="java.desktop,java.naming..."/>
    <fx:limit-modules value="java.base"/>
    <fx:limit-modules value="java.desktop,java.naming..."/>
    <fx:module-path value="${java.home}/../images/jmods"/>
    <fx:module-path value="${build.dir/modules"/>
</fx:runtime>
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 1
    Thanks but as I mentioned I’m already using those options. The problem is that they aren’t being honored. – GabeV Oct 22 '17 at 19:44
  • @GabeV Could you share the exact command/task used by you in that case and what error/output did you get? – Naman Oct 23 '17 at 00:57
  • Not getting any errors. The output I pasted shows that it just reverts to adding all the modules. I edited the question with the command I run. One possibility that occurs to me is that the main jar for the bundle is not a module jar. I think that is preventing it from using only specified modules. I'm trying to convert it to a module jar to confirm, but having other issues. – GabeV Oct 23 '17 at 03:03