1

我目前正在尝试从 jdk 中提取预览类文件,例如 jrt-fs.jar 中的 java.lang.Record (在 libs 文件夹中),但是在迭代它时找不到预览类,例如 Record 。这是我正在使用的代码:

Path jrtFsJar = jdk15Home.resolve("lib").resolve("jrt-fs.jar");
jrtFsJarLoader = new URLClassLoader(new URL[] {jrtFsJar.toUri().toURL()});
FileSystem jrtFs = FileSystems.newFileSystem(
    URI.create("jrt:/"), 
    Collections.emptyMap(), 
    jrtFsJarLoader);
Files.walk(jrtFs.getPath("/modules")).forEach(path -> 
   // Here is walks over classes such as "modules/java.base/java/lang/Object.class"
   // but not over "modules/java.base/java/lang/Record.class"
)

我也尝试过更直接的方法:

FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
// Object works, I get the bytes.
byte[] object = Files.readAllBytes(jrtFs.getPath("modules", "java.base",
                                          "java/lang/Object.class"));
// Record fails, NoSuchFile.  
byte[] object = Files.readAllBytes(jrtFs.getPath("modules", "java.base",
                                          "java/lang/Record.class"));

现在,当我使用 --enable-preview 运行完全相同的 jdk 时,我可以使用记录。

如何从 jdk linux/lib 中提取 Record 类?预览课程在里面还是我应该在其他地方寻找它们?我需要一个特定的标志来访问它们吗?

任何帮助表示赞赏。

4

1 回答 1

3

当您在已经有 jrt 文件系统的 JDK 上运行时,您可以更轻松地访问另一个 JDK 的 jrt 文件系统。

FileSystem jrtFs = FileSystems.newFileSystem(
    URI.create("jrt:/"), Map.of("java.home", jdk15Home.toString()));
byte[] object = Files.readAllBytes(
    jrtFs.getPath("modules", "java.base", "java/lang/Record.class"));

内置文件系统将为外部 JDK 的 jrt-fs.jar 创建一个特殊的类加载器,该类加载器不会委托给该 jar 的类的父加载器。所以它不会再次以自己的方式结束。

由于它使用其他 JDK 提供的实现,因此它将能够使用完全不同的数据格式进行模块存储来处理更新的功能甚至 JDK。

于 2021-02-04T11:19:40.670 回答