如何从命令行检查JVM模块的内容?

4
我想从命令行检查本地安装的jvm中java模块的资源文件内容。根据有关jvm中mime类型支持的问题, 我想看到在模块java.base/sun/net/www/content-types.properties的内容。但是,当浏览已安装的jvm文件时,我找不到名为java.base.*的文件。但是我看到一个大小为130 MB以上的文件./lib/modules。我怀疑这个文件包含了模块java.base的内容。但是7-zip无法将此文件打开为存档文件。我如何使用命令行查看本地安装的jvm中java模块java.base/sun/net/www/content-types.properties的内容?
2个回答

6
使用jimage工具从modules中提取content-types.properties
jimage extract --dir /tmp --include regex:.*content-types.properties $JAVA_HOME/lib/modules && \
cat /tmp/java.base/sun/net/www/content-types.properties

我曾经在某个地方看到过这个工具的存在,但是后来在这里找不到相关文档,所以我认为我可能错了或者它是一个“私有”的工具。 - Slaw

4

我不知道有没有一个命令行工具可以做到这一点,但这并不意味着不存在这样的工具。不过,您可以编写一个快速的实用程序,在不到20行的代码中获取资源内容。

请注意,目前已实现的所有三种方法都从执行程序的JDK中读取资源。此外,您可以显然修改任一方法的代码以更好地满足您的需求,例如使它们更加“动态”(例如,接受命令行参数)。


使用资源API

一种选择是使用资源API:

import java.io.IOException;

public class Main {

  public static void main(String[] args) throws IOException {
    var name = "/sun/net/www/content-types.properties";
    try (var in = Object.class.getResourceAsStream(name)) {
      // Thanks to Holger for the code simplification
      in.transferTo(System.out);
    }
  }
}

注意: 在调用java.base模块中的类上使用getResourceAsStream方法。

然后你可以像下面这样运行它(利用“单一源文件”功能):

java --add-opens=java.base/sun.net.www=ALL-UNNAMED Main.java

使用ModuleReader

import java.io.IOException;
import java.lang.module.ModuleFinder;

public class Main {

  // Thanks to Holger for pointing out this approach
  public static void main(String[] args) throws IOException {
    var name = "sun/net/www/content-types.properties";

    var mod = ModuleFinder.ofSystem().find("java.base").orElseThrow();
    try (var reader = mod.open();
         var in = reader.open(name).orElseThrow()) {
      in.transferTo(System.out);
    }
  }
}

通过这种方法,您不需要使用 --add-opens 参数。


使用 JRT 文件系统

第三个选项是使用 JRT 文件系统并像读取文件一样读取资源:

import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;

public class Main {

  public static void main(String[] args) throws IOException {
    var uri = URI.create("jrt:/java.base/sun/net/www/content-types.properties");
    try (var in = Files.newInputStream(Path.of(uri))) {
      // Thanks to Holger for code simplification
      in.transferTo(System.out);
    }
  }
}

使用此选项,您无需--add-opens参数。


1
这实际上可以与启动单文件源代码程序结合使用,无需任何编译步骤。 - SpaceTrucker
已更新答案,无需单独的显式编译步骤。 - Slaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接