27

JRE-9/lib目录中(至少在 Windows 上),有一个名为的新文件modules,其大小约为 107 MB。是否可以提取该文件或在其中列出 java 模块?

我可以看到一个名为jmodat 的新工具可用jdk-9/bin/jmod.exe,但它用于读取.jmod位于 at 的文件jdk-9/jmods,它无法读取该文件modules

4

6 回答 6

29

modules文件是一个容器文件。它是 JDK 内部的,格式没有记录(可能随时更改)。出于故障排除的目的,jimage可以使用 bin 目录中的工具列出或提取内容。

于 2017-09-27T06:38:07.623 回答
19

运行时资源以向后兼容的方式处理。例如,当你这样做时

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

在过去,你通常会得到类似的东西

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

在 Java 9 下运行同样的程序会给你

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

反而。无论哪种情况,您都可以在其上打开一个FileSystem以检查其他可用资源(从 Java 7 开始)。虽然ZipFileSystem必须先通过创建FileSystems.newFileSystem,但 Java 9 的文件系统甚至已经开放使用:

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?).");
    }
}

如果您在与要检查的 JRE 不同的 JRE 下运行,则必须首先手动加载适当的文件系统实现,但这为检查 Java 9 安装提供了可能性,即使是从 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();
        }
    }
}

一旦你有了一个文件系统(或一个文件系统Path),你就可以使用所有的标准功能,例如Files检查或提取/复制数据,尽管正确的术语是在不同的文件系统中“存储一个等效的类文件” ,因为运行时映像的表示根本不必是类文件。

于 2017-09-27T15:37:36.523 回答
7

modules文件是一个单独的文件(不打算在任何地方提取),其中包含 JDK 中存在的所有模块的二进制表示,采用非文档格式,可能会发生变化。您可以使用 列出它包含的模块java --list-modules

最初,该modules文件将包含每个模块,并且基本上是 JDK 本身的两倍,但是一旦您使用该jlink实用程序“缩小”您的 JDK,该modules文件将变得更小(假设您的程序包含 JDK 提供的模块的子集)。有关更多信息,jlink请参见此处: http: //openjdk.java.net/jeps/282

于 2017-09-27T02:50:32.353 回答
3

您可以通过列出模块java --list-modules

于 2017-09-27T02:49:11.170 回答
3

您可以使用

$ jimage list $JAVA_HOME/lib/modules

列出所有系统包的名称,如“java/io/EOFException.class”等。

另外,您可以使用

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

将所有 .class 文件提取到指定目录中。

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

于 2020-04-13T03:41:16.763 回答
0

您可以使用 libjimage 来读取此文件。

于 2018-03-08T11:06:35.500 回答