I have been working with JLink to create minimal JRE for various Spring Boot applications. I have successfully done this manually by figuring out the required Modules via trial and error. After successfully doing this I have been attempting to automate this process using JDeps.
First attempt was to scan the built Jar for my application. I am using Java 14 jdeps to analyze a Java 11 codebase.
jdeps --class-path BOOT-INF/classes --module-path BOOT-INF/lib/,${JAVA_HOME}/jmods --add-modules=ALL-MODULE-PATH --list-deps target/camel-account-sapi-0.0.2-SNAPSHOT.jar
Which results in several not found dependencies.
Error: Missing dependencies: classes not found from the module path and classpath.
To suppress this error, use --ignore-missing-deps to continue.
camel-account-sapi-0.0.2-SNAPSHOT.jar
com.ms3.camelaccountsapi.CamelAccountSapiApplication -> org.springframework.boot.SpringApplication not found
com.ms3.camelaccountsapi.CamelAccountSapiApplication -> org.springframework.boot.autoconfigure.SpringBootApplication not found
com.ms3.camelaccountsapi.CamelAccountSapiApplication -> org.springframework.context.ConfigurableApplicationContext not found
com.ms3.camelaccountsapi.routes.GeneratedRoutesInterface -> org.apache.camel.builder.RouteBuilder not found
com.ms3.camelaccountsapi.routes.GeneratedRoutesInterface -> org.apache.camel.model.rest.RestDefinition not found
com.ms3.camelaccountsapi.routes.GeneratedRoutesInterface -> org.apache.camel.model.rest.RestOperationParamDefinition not found
com.ms3.camelaccountsapi.routes.GeneratedRoutesInterface -> org.apache.camel.model.rest.RestParamType not found
com.ms3.camelaccountsapi.routes.GeneratedRoutesInterface -> org.springframework.stereotype.Component not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> com.datasonnet.document.MediaTypes not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.Exchange not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.Expression not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.LoggingLevel not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.Predicate not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.builder.DatasonnetBuilder not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.builder.RouteBuilder not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.builder.SimpleBuilder not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.builder.ValueBuilder not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.model.ChoiceDefinition not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.model.OnExceptionDefinition not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.model.ProcessorDefinition not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.apache.camel.model.RouteDefinition not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.slf4j.Logger not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.slf4j.LoggerFactory not found
com.ms3.camelaccountsapi.routes.RoutesImplementation -> org.springframework.stereotype.Component not found
org.springframework.boot.loader.PropertiesLauncher -> org.springframework.util.Assert not found
org.springframework.boot.loader.jarmode.JarModeLauncher -> org.springframework.core.io.support.SpringFactoriesLoader not found
org.springframework.boot.loader.jarmode.JarModeLauncher -> org.springframework.util.ClassUtils not found
Adding --ignore-missing-deps
results in something more meaning full but incomplete:
java.base
java.logging
Next I extracted the applications using java -Djarmode=layertools -jar ./target/camel-account-sapi-0.0.2-SNAPSHOT.jar extract
This gives me the BOOT-INF/lib folder containing all 150 of the JAR dependancies. So I attempted to run a similar JDeps command as before with a few extra options:
jdeps --module-path temp/BOOT-INF/lib/,${JAVA_HOME}/jmods --add-modules=ALL-MODULE-PATH --multi-release 11 --list-deps --ignore-missing-deps --recursive --compile-time temp/BOOT-INF/lib/*
This however results in an Exception
Exception in thread "main" java.lang.module.FindException: Module java.annotation not found, required by org.apache.tomcat.embed.core
at java.base/java.lang.module.Resolver.findFail(Resolver.java:894)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:140)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:422)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:256)
at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:564)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:603)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:557)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
at jdk.jdeps/com.sun.tools.jdeps.Main.main(Main.java:49)
I noticed that some of the JARs in the /lib folder could successfully be analyzed so I wrote a Bash script to run the same command on each of the /lib jars while ignoring exceptions. 15 of the 150 fail to be analyzed due to Module not found
however the resulting list of required Modules from the other 135 is quite close. It is only missing one required Module jdk.crypto.ec
and found all others:
java.sql,java.security.jgss,java.logging,java.xml,java.compiler,jdk.unsupported,java.transaction.xa,java.rmi,java.management,java.instrument,java.naming,java.base,java.datatransfer,jdk.httpserver,java.scripting,java.desktop,java.prefs
Am I going in the wrong direction? Or what could/should be done to resolved these missing Module issues? I believe, for example that the "Missing" module above java.annotation
may exist in one of the other JARs? I believe this to be the case even more so due to a few of the other 15 failed jdeps commands.
temp/BOOT-INF/lib/tomcat-embed-core-9.0.38.jar
Exception in thread "main" java.lang.module.FindException: Module java.annotation not found, required by org.apache.tomcat.embed.core
at java.base/java.lang.module.Resolver.findFail(Resolver.java:894)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:140)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:422)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:256)
at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:564)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:603)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:557)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
at jdk.jdeps/com.sun.tools.jdeps.Main.main(Main.java:49)
error
temp/BOOT-INF/lib/tomcat-embed-websocket-9.0.38.jar
Exception in thread "main" java.lang.module.FindException: Module org.apache.tomcat.embed.core not found, required by org.apache.tomcat.embed.websocket
at java.base/java.lang.module.Resolver.findFail(Resolver.java:894)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
at java.base/java.lang.module.Resolver.resolve(Resolver.java:140)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:422)
at java.base/java.lang.module.Configuration.resolve(Configuration.java:256)
at jdk.jdeps/com.sun.tools.jdeps.JdepsConfiguration$Builder.build(JdepsConfiguration.java:564)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.buildConfig(JdepsTask.java:603)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:557)
at jdk.jdeps/com.sun.tools.jdeps.JdepsTask.run(JdepsTask.java:533)
at jdk.jdeps/com.sun.tools.jdeps.Main.main(Main.java:49)
error
I'm working through a very similar issue right now. It looks like between tomcat embed 9.0.37 and 9.0.38 explicit module-info's were defined. The names of modules changed compared to automatic modules.
java.annotation
module is the name exported from the annotations-api.jar. I have no idea why it uses that name. I'm sure there is a reason, I just don't understand it.org.apache.tomcat.embed.jasper.el
changed toorg.apache.tomcat.embed.el
I'm not sure how far that's going to get you, but it's perhaps a start.