问题描述
我目前正试图从 jdk 中提取预览类文件,例如 jrt-fs.jar(在 libs 文件夹中)中的 java.lang.Record,但它在迭代时找不到诸如 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/lang/Record.class"));
现在,当我使用 --enable-preview 运行完全相同的 jdk 时,我可以使用记录。
如何从 jdk linux/lib 中提取 Record 类?预览类是在里面还是我应该在别处寻找它们?我需要一个特定的标志来访问它们吗?
感谢任何帮助。
解决方法
当您在已经有 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。