25

In JRE-9/lib directory (at least on Windows), there is a new file called modules whose size is about 107 MB. Is it possible to extract that file or maybe list java modules within it?

I can see that a new tool called jmod is available at jdk-9/bin/jmod.exe, but that is for reading .jmod files which is located at jdk-9/jmods and it cannot read the file modules.

Naman
  • 23,555
  • 22
  • 173
  • 290
Eng.Fouad
  • 107,075
  • 62
  • 298
  • 390

6 Answers6

26

The modules file is a container file. It's internal to the JDK and the format is not documented (it may change at any time). For troubleshooting purposes, the jimage tool in the bin directory can be used to list or extract the contents.

Alan Bateman
  • 4,734
  • 1
  • 14
  • 25
  • 2
    any links to `jimage` and how it can be used would be useful as well. – Naman Sep 27 '17 at 08:46
  • 8
    There isn't a docs page for jimage but `jimage --help` should have enough. Note that the tool is included for troubleshooting/support usages, it's not something that most developers will ever need. – Alan Bateman Sep 27 '17 at 09:46
  • 1
    Worked for me. Just did `$ jimage extract $JAVA_HOME/lib/modules` and poof! – 0xbe5077ed Dec 09 '17 at 10:45
17

The runtime resources are handled in a backwards compatible way. E.g. when you did

URL url = Object.class.getResource("Object.class");
System.out.println(url);

in the past, you usually got something like

jar:file:/path-to-jre/lib/rt.jar!/java/lang/Object.class

Running the same under Java 9 will give you

jrt:/java.base/java/lang/Object.class

instead. In either case, you can open a FileSystem on it to inspect the other available resources (since Java 7). While the ZipFileSystem had to be created via FileSystems.newFileSystem first, Java 9’s file system is even already open for use:

private static void readMyOwnJRE() throws IOException {
    try {
        Path p = Paths.get(URI.create("jrt:/")).resolve("/modules");
        System.out.println("My own JRE's modules:");
        Files.list(p).forEach(m -> System.out.println(m.getFileName()));
        System.out.println();
    } catch(FileSystemNotFoundException ex) {
        System.out.println("Could not read my modules (perhaps not Java 9?).");
    }
}

If you are running under a different JRE than the one you want to inspect, you have to load the appropriate file system implementation manually first, but this opens the possibility to inspect a Java 9 installation even from a Java 8 JRE:

public static void readOtherJRE(Path pathToJRE) throws IOException {
    Path p = pathToJRE.resolve("lib").resolve("jrt-fs.jar");
    if(Files.exists(p)) {
        try(URLClassLoader loader = new URLClassLoader(new URL[]{ p.toUri().toURL() });
            FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
                                                      Collections.emptyMap(),
                                                      loader)) {
            System.out.println("Modules of "+pathToJRE);
            Files.list(fs.getPath("/modules")).forEach(System.out::println);
            System.out.println();
        }
    }
}

Once you have a file system (or a Path into it), you can use all standard functions of, e.g. Files to inspect or extract/copy the data, though the right term would be “to store an equivalent class file” in a different file system, as the runtime image’s representation doesn’t have to be a class file at all.

Holger
  • 243,335
  • 30
  • 362
  • 661
6

The modules file is meant to be a single file (not meant to be extracted anywhere) which contains a binary representation of all of the modules present in the JDK in an undocument format which is subject to change. You can list the modules it contains with java --list-modules.

Initially the modules file will contain every module and basically double the side of the JDK on its own, but once you "minify" your JDK using the jlink utility, the modules file will become smaller (assuming your program contains a subset of the modules provided with the JDK). For more info on jlink see here: http://openjdk.java.net/jeps/282

Andy Guibert
  • 34,857
  • 7
  • 32
  • 54
3

You can list modules via java --list-modules

ZhekaKozlov
  • 29,055
  • 16
  • 100
  • 138
1

you can use

$ jimage list $JAVA_HOME/lib/modules

to list all the system packages' name,like "java/io/EOFException.class",etc.

also,you can use

$ jimage extract --dir=<directory>  $JAVA_HOME/lib/modules

to extract all the .class files into the specified directory.

reference:https://adoptopenjdk.gitbooks.io/adoptopenjdk-getting-started-kit/en/intermediate-steps/openjdk9-jimage.html

xxllxx666
  • 11
  • 2
0

You can use libjimage to read this file.

Glavo
  • 359
  • 1
  • 8