Как распаковать файл jre-9/lib/modules?
В JRE-9/lib
каталог (по крайней мере, в Windows), есть новый файл с именем modules
размер которого составляет около 107 МБ. Можно ли извлечь этот файл или список Java-модулей в нем?
Я вижу, что новый инструмент под названием jmod
доступен на jdk-9/bin/jmod.exe
, но это для чтения .jmod
файлы, которые расположены в jdk-9/jmods
и он не может прочитать файл modules
,
5 ответов
modules
файл является контейнерным файлом. Он является внутренним по отношению к JDK, и формат не задокументирован (он может измениться в любое время). В целях устранения неполадок jimage
Инструмент в каталоге bin можно использовать для просмотра или извлечения содержимого.
Ресурсы времени выполнения обрабатываются обратно совместимым способом. Например, когда ты сделал
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:/modules"));
System.out.println("My own JRE's modules:");
Files.list(p).forEach(System.out::println);
System.out.println();
} catch(FileSystemNotFoundException ex) {
System.out.println("Could not read my modules (perhaps not Java 9?).");
}
}
Если вы работаете под 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
для проверки или извлечения / копирования данных, хотя правильным термином было бы "хранить файл эквивалентного класса" в другой файловой системе, поскольку представление образа во время выполнения вовсе не должно быть файлом класса.
modules
Файл должен быть одним файлом (не предназначенным для извлечения в любом месте), который содержит двоичное представление всех модулей, присутствующих в JDK, в недокументированном формате, который может быть изменен. Вы можете перечислить модули, которые он содержит java --list-modules
,
Первоначально modules
файл будет содержать каждый модуль и в основном удваивать сторону JDK сам по себе, но как только вы "минимизируете" свой JDK, используя jlink
утилита, modules
файл станет меньше (при условии, что ваша программа содержит подмножество модулей, поставляемых с JDK). Для получения дополнительной информации о jlink
смотрите здесь: http://openjdk.java.net/jeps/282
Вы можете использовать
$ jimage list $JAVA_HOME/lib/modules
чтобы перечислить имена всех системных пакетов, например "java/io/EOFException.class" и т. д.
также вы можете использовать
$ jimage extract --dir=<directory> $JAVA_HOME/lib/modules
для извлечения всех файлов.class в указанный каталог.