javamodulejava-17java-module

Why java.se module isn't loaded?


I use Java 17 and I am trying to load all Java SE modules (not JDK).

The code I try:

AtomicInteger y = new AtomicInteger();
ModuleLayer.boot().modules().stream()
        .map(Module::getName)
        .sorted()
        .filter(x -> x.startsWith("ja") && !x.equals("java.smartcardio"))
        .forEach(x -> System.out.println("#" + y.incrementAndGet() + " | " + x));

The predicates inside the filter help me keep only the Java SE modules (which java.se belongs in as we see here: https://docs.oracle.com/en/java/javase/17/docs/api/index.html). But even If I remove them, the module is not returned.

I see the java.se module in the filesystem (inside lib/src.zip/... and legal/java.se). It even exists in the ExternalLibraries of my IDE (Intellij):

enter image description here

The output of the code:

enter image description here


Solution

  • I’m assuming that you are running your code as part of a non-modular (classpath) application, as otherwise the module’s requires directive(s) would control which modules are present.

    The policy for such applications has changed with Java 11. In previous versions, the java.se module was used as root module for non-modular applications if it existed.

    java.lang.module documentation of Java 10:

    The set of root modules at compile-time is usually the set of modules being compiled. At run-time, the set of root modules is usually the application module specified to the 'java' launcher. When compiling code in the unnamed module, or at run-time when the main application class is loaded from the class path, then the default set of root modules is implementation specific (In the JDK implementation it is the module "java.se", if observable, and every observable module that exports an API).

    java.lang.module documentation of Java 11:

    The set of root modules at compile-time is usually the set of modules being compiled. At run-time, the set of root modules is usually the application module specified to the 'java' launcher. When compiling code in the unnamed module, or at run-time when the main application class is loaded from the class path, then the default set of root modules is implementation specific. In the JDK the default set of root modules contains every module that is observable on the upgrade module path or among the system modules, and that exports at least one package without qualification.

    (Emphasis added by me in either citation)

    This new policy excludes java.se itself because it does not “export[s] at least one package”.

    Compare with JDK-8205169:

    This [old] policy is problematic when creating a run-time image that contains java.se and also contains a java.* module that is not in Java SE but exports an API, e.g. java.json. When compiling or running non-modular code, a developer needs to specify --add-modules to ensure that the non-Java SE java.* modules in the run-time image are resolved.

    A second point is that the original policy was created to ensure that the java.corba and Java EE modules (that existed in Java SE 9 and 10) were not resolved by default. These modules are proposed to be dropped from Java SE 11 so this aspect of the policy is no longer relevant.

    Change the policy so that the default set of root modules is simply all observable modules on the upgrade module path or among the system modules that exports at least one package, without qualification.