I'm building my first modular app with Java 11 and Maven 3.6.1. My IDE is IntellijIDEA 2019.1.3. I added a module 'app' and added module-info.java
, but I'm confused because my app is working even I added spring dependencies to the app module and I didn't open my module or some package in the module for reflection.
I added module-info.java
with my IDE's feature and it forces me to add requires
statements. So far so good. But why it works without opening the module for reflection? Is that some new feature in Java 11 or in my IDE version? Am I doing something wrong?
My module-info.java
:
module app {
requires spring.web;
requires spring.webmvc;
requires javax.servlet.api;
requires spring.context;
}
I tried to find the answer on SO and JetBrains, but I failed.
I am looking at this guy (https://youtu.be/hxsCYxZ1gXU?t=2238) working with spring modules and his IDE requires him to open the module for reflection. And I downloaded his project and deleted opens
statements and it still compiles in my IDE.
And one more question: How can I examine the module-path with my IDE? How can I see which modules are there and what is on my classpath (right now there should be nothing)?
EDIT: I just realized that my IDE prints Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED
log. I suppose this is the reason, but I can't find where this arg is coming from. Am I on the right trail?
EDIT No. 2: In the console log, as command-line arguments are:
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
-Djava.util.logging.config.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\conf\logging.properties
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djdk.module.showModuleResolution=true
-Dcom.sun.management.jmxremote=
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.password.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\jmxremote.password
-Dcom.sun.management.jmxremote.access.file=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems\jmxremote.access
-Djava.rmi.server.hostname=127.0.0.1
-Djdk.tls.ephemeralDHKeySize=2048
-Djava.protocol.handler.pkgs=org.apache.catalina.webresources
-Dignore.endorsed.dirs=
-Dcatalina.base=C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems
-Dcatalina.home=D:\tomcat\apache-tomcat-9.0.21
-Djava.io.tmpdir=D:\tomcat\apache-tomcat-9.0.21\temp
Also, from my log (I'm not sure is this relevant):
D:\tomcat\apache-tomcat-9.0.21\bin\catalina.bat run
[2019-11-08 05:42:34,404] Artifact app:war exploded: Waiting for server connection to start artifact deployment...
Using CATALINA_BASE: "C:\Users\Nedim\.IntelliJIdea2019.2\system\tomcat\Unnamed_ems"
Using CATALINA_HOME: "D:\tomcat\apache-tomcat-9.0.21"
Using CATALINA_TMPDIR: "D:\tomcat\apache-tomcat-9.0.21\temp"
Using JRE_HOME: "C:\Program Files\Java\jdk-11.0.5"
Using CLASSPATH: "D:\tomcat\apache-tomcat-9.0.21\bin\bootstrap.jar;D:\tomcat\apache-tomcat-9.0.21\bin\tomcat-juli.jar"
--show-module-resolution
prints out:
root java.sql jrt:/java.sql
root jdk.management.jfr jrt:/jdk.management.jfr
root java.rmi jrt:/java.rmi
root jdk.jdi jrt:/jdk.jdi
root java.transaction.xa jrt:/java.transaction.xa
root java.xml.crypto jrt:/java.xml.crypto
root java.logging jrt:/java.logging
root java.xml jrt:/java.xml
root jdk.xml.dom jrt:/jdk.xml.dom
root jdk.jfr jrt:/jdk.jfr
root java.datatransfer jrt:/java.datatransfer
root jdk.httpserver jrt:/jdk.httpserver
root jdk.net jrt:/jdk.net
root java.naming jrt:/java.naming
root java.desktop jrt:/java.desktop
root java.prefs jrt:/java.prefs
root java.net.http jrt:/java.net.http
root jdk.compiler jrt:/jdk.compiler
root java.security.sasl jrt:/java.security.sasl
root jdk.jconsole jrt:/jdk.jconsole
root jdk.attach jrt:/jdk.attach
root java.base jrt:/java.base
root jdk.javadoc jrt:/jdk.javadoc
root jdk.management.agent jrt:/jdk.management.agent
root jdk.jshell jrt:/jdk.jshell
root jdk.jsobject jrt:/jdk.jsobject
root java.sql.rowset jrt:/java.sql.rowset
root java.management jrt:/java.management
root jdk.sctp jrt:/jdk.sctp
root java.smartcardio jrt:/java.smartcardio
root jdk.unsupported jrt:/jdk.unsupported
root jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
root java.instrument jrt:/java.instrument
root java.security.jgss jrt:/java.security.jgss
root jdk.management jrt:/jdk.management
root jdk.security.auth jrt:/jdk.security.auth
root java.compiler jrt:/java.compiler
root java.scripting jrt:/java.scripting
root jdk.dynalink jrt:/jdk.dynalink
root jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
root jdk.accessibility jrt:/jdk.accessibility
root jdk.jartool jrt:/jdk.jartool
root java.management.rmi jrt:/java.management.rmi
root jdk.security.jgss jrt:/jdk.security.jgss
jdk.security.jgss requires java.security.sasl jrt:/java.security.sasl
jdk.security.jgss requires java.logging jrt:/java.logging
jdk.security.jgss requires java.security.jgss jrt:/java.security.jgss
java.management.rmi requires java.naming jrt:/java.naming
java.management.rmi requires java.rmi jrt:/java.rmi
java.management.rmi requires java.management jrt:/java.management
jdk.accessibility requires java.desktop jrt:/java.desktop
jdk.unsupported.desktop requires java.desktop jrt:/java.desktop
jdk.dynalink requires java.logging jrt:/java.logging
jdk.security.auth requires java.naming jrt:/java.naming
jdk.security.auth requires java.security.jgss jrt:/java.security.jgss
jdk.management requires java.management jrt:/java.management
java.security.jgss requires java.naming jrt:/java.naming
jdk.scripting.nashorn requires jdk.dynalink jrt:/jdk.dynalink
jdk.scripting.nashorn requires java.logging jrt:/java.logging
jdk.scripting.nashorn requires java.scripting jrt:/java.scripting
java.sql.rowset requires java.logging jrt:/java.logging
java.sql.rowset requires java.sql jrt:/java.sql
java.sql.rowset requires java.naming jrt:/java.naming
jdk.jsobject requires java.desktop jrt:/java.desktop
jdk.jshell requires jdk.compiler jrt:/jdk.compiler
jdk.jshell requires java.compiler jrt:/java.compiler
jdk.jshell requires java.logging jrt:/java.logging
jdk.jshell requires java.prefs jrt:/java.prefs
jdk.jshell requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.jshell requires jdk.internal.le jrt:/jdk.internal.le
jdk.jshell requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jshell requires jdk.jdi jrt:/jdk.jdi
jdk.management.agent requires java.management jrt:/java.management
jdk.management.agent requires java.management.rmi jrt:/java.management.rmi
jdk.javadoc requires java.compiler jrt:/java.compiler
jdk.javadoc requires java.xml jrt:/java.xml
jdk.javadoc requires jdk.compiler jrt:/jdk.compiler
jdk.attach requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires java.desktop jrt:/java.desktop
jdk.jconsole requires jdk.management.agent jrt:/jdk.management.agent
jdk.jconsole requires jdk.attach jrt:/jdk.attach
jdk.jconsole requires java.management.rmi jrt:/java.management.rmi
jdk.jconsole requires java.management jrt:/java.management
jdk.jconsole requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires jdk.management jrt:/jdk.management
jdk.jconsole requires java.rmi jrt:/java.rmi
java.security.sasl requires java.logging jrt:/java.logging
jdk.compiler requires java.compiler jrt:/java.compiler
java.prefs requires java.xml jrt:/java.xml
java.desktop requires java.xml jrt:/java.xml
java.desktop requires java.prefs jrt:/java.prefs
java.desktop requires java.datatransfer jrt:/java.datatransfer
java.naming requires java.security.sasl jrt:/java.security.sasl
jdk.xml.dom requires java.xml jrt:/java.xml
java.xml.crypto requires java.xml jrt:/java.xml
java.xml.crypto requires java.logging jrt:/java.logging
jdk.jdi requires jdk.attach jrt:/jdk.attach
jdk.jdi requires jdk.jdwp.agent jrt:/jdk.jdwp.agent
java.rmi requires java.logging jrt:/java.logging
jdk.management.jfr requires jdk.jfr jrt:/jdk.jfr
jdk.management.jfr requires java.management jrt:/java.management
jdk.management.jfr requires jdk.management jrt:/jdk.management
java.sql requires java.logging jrt:/java.logging
java.sql requires java.transaction.xa jrt:/java.transaction.xa
java.sql requires java.xml jrt:/java.xml
jdk.dynalink binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
java.naming binds jdk.naming.rmi jrt:/jdk.naming.rmi
java.naming binds jdk.naming.dns jrt:/jdk.naming.dns
java.management binds java.management.rmi jrt:/java.management.rmi
java.management binds jdk.management jrt:/jdk.management
java.management binds jdk.management.jfr jrt:/jdk.management.jfr
java.compiler binds jdk.compiler jrt:/jdk.compiler
java.compiler binds jdk.javadoc jrt:/jdk.javadoc
java.base binds jdk.zipfs jrt:/jdk.zipfs
java.base binds jdk.localedata jrt:/jdk.localedata
java.base binds jdk.security.jgss jrt:/jdk.security.jgss
java.base binds java.security.jgss jrt:/java.security.jgss
java.base binds jdk.crypto.cryptoki jrt:/jdk.crypto.cryptoki
java.base binds java.smartcardio jrt:/java.smartcardio
java.base binds jdk.crypto.mscapi jrt:/jdk.crypto.mscapi
java.base binds jdk.crypto.ec jrt:/jdk.crypto.ec
java.base binds java.security.sasl jrt:/java.security.sasl
java.base binds java.naming jrt:/java.naming
java.base binds java.xml.crypto jrt:/java.xml.crypto
java.base binds jdk.jdeps jrt:/jdk.jdeps
java.base binds jdk.javadoc jrt:/jdk.javadoc
java.base binds jdk.jlink jrt:/jdk.jlink
java.base binds jdk.jartool jrt:/jdk.jartool
java.base binds jdk.compiler jrt:/jdk.compiler
java.base binds java.desktop jrt:/java.desktop
java.base binds java.management jrt:/java.management
java.base binds jdk.security.auth jrt:/jdk.security.auth
java.base binds java.logging jrt:/java.logging
java.base binds jdk.charsets jrt:/jdk.charsets
jdk.jshell binds jdk.editpad jrt:/jdk.editpad
java.desktop binds jdk.accessibility jrt:/jdk.accessibility
java.desktop binds jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
java.datatransfer binds java.desktop jrt:/java.desktop
java.scripting binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
jdk.internal.jvmstat binds jdk.jstatd jrt:/jdk.jstatd
jdk.jstatd requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jstatd requires java.rmi jrt:/java.rmi
jdk.editpad requires java.desktop jrt:/java.desktop
jdk.editpad requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.jlink requires jdk.jdeps jrt:/jdk.jdeps
jdk.jlink requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jdeps requires java.compiler jrt:/java.compiler
jdk.jdeps requires jdk.compiler jrt:/jdk.compiler
jdk.crypto.cryptoki requires jdk.crypto.ec jrt:/jdk.crypto.ec
jdk.naming.dns requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.rmi jrt:/java.rmi
--show-module-resolution
flag. – Affenpinscherjava.base
to unnamed modules, it’s not opening your module to other modules. – Wilonahjava.base
is a root of the JDK modular platform and it is transitively part of every module. But how framework rich my class? – BlackberryModule Dependencies
<--- empty folder – Blackberrymodule-info.java
put the module on module-path!? – Blackberrymodule-info.class
is irrelevant when it is present on the class path. It has to be on the module path, which is a distinct runtime option, e.g. on the command line, it’s--class-path
vs--module-path
. A countercheck to--show-module-resolution
is to print the class path, e.g. putSystem.out.println("classpath: "+System.getProperty("java.class.path"));
into your application. It should be empty or at least not referring to Spring jars. Otherwise, it’s not a module resp. in the unnamed module. – Wilonah--module-path
in the log at all and consistently, the module resolution doesn’t even show your ownapp
module. So I suppose, Tomcat is loading your code, as well as Spring, through a custom class loader, that’s why neither appears in the class path. However, loading via custom class loader can be done modular or old style. Mind that a simpleSystem.out.println(SomeClass.class.getModule());
will tell you whether it belongs to a declared module or the unnamed module. You can do it for one of your classes, as well as a Spring specific class… – Wilonahsout
line toWebbAppInitializer.class
which brings up Spring context and also one toTestController.class
and got this two logs: >>> Logging from WebbAppInitializer.class: unnamed module @43c2e470 and >>> Logging from TestController.class: unnamed module @43c2e470. Since they are both in theapp
module, the same mamory location is printed in both cases. So you supposed well! And what would be the right thing to do regarding this situation, what options do I have? – Blackberry