如何提取文件jre-9/lib/modules?

How to extract the file jre-9/lib/modules?

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

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

您可以通过 java --list-modules

列出模块

modules 文件是一个单独的文件(并不意味着要提取到任何地方),它包含 JDK 中存在的所有模块的二进制表示,格式为无文档格式可能会发生变化。您可以使用 java --list-modules.

列出它包含的模块

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

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

运行时资源以向后兼容的方式处理。例如。你什么时候做的

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)。虽然必须先通过 FileSystems.newFileSystem 创建 ZipFileSystem,但 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 检查或 extract/copy 数据,尽管正确的术语是在不同的文件系统中“存储等效的 class 文件”,因为运行时图像的表示不必完全是一个 class 文件。

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

你可以使用

$ 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