0

我用新的内存选项重新启动了一个 Java 进程,-Xms4G -Xmx4G -XX:MaxDirectMemorySize=6G并想验证这些更改是否正确应用,尤其是 6G 的直接内存。

我发现验证这一点的第一个解决方案是通过java它自己,但这只是报告了一个0,暗示我的新设置没有效果:

bash-4.4$ java -XX:+PrintFlagsFinal -version | grep MaxDirect
    uintx MaxDirectMemorySize                = 0                          {product}
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

我后来发现的第二个解决方案是 via jinfo,这显然证实了6G我打算设置的:

bash-4.4$ jinfo -flag MaxDirectMemorySize 1
-XX:MaxDirectMemorySize=6442450944

我以前依赖于java -XX:+PrintFlagsFinal其他目的,但现在我想知道为什么它不返回预期值。为什么javajinfo返回不同的结果?

4

1 回答 1

1

(至少)有两个不同的 JVM。

[扩展注释:]java {nothing} -XX:+PrintFlagsFinal -version创建一个新的 JVM,不更改其默认配置,并打印生成的配置,这是没有更改的默认配置 - MaxDirectMemSize 的默认值确实为零。

OTOHjinfo {option} pid附加到现有的已经运行的JVM 并获取或更改该 JVM 的配置(尽管特定的 pid 1 通常不是 JVM,但它通常在您使用的 docker 容器中)。jps列出您可以附加到的正在运行的 JVM,以及包含 JVM 参数和/或应用程序参数的选项。

这是否意味着无法实现相同的验证java?不像jinfo它不能附加到正在运行的JVM?

是与否;它有点仙境。

java 它本身会创建一个新的 JVM,与任何现有的 JVM 分开。通常这个 JVM 运行一个用户指定的程序,但是-version当你使用它时,它只是打印版本信息并退出而不运行任何东西。

现在,附加 API可以从 Java 访问(并且实际上部分是用 Java 编写的)。jinfo更详细的是:

  1. 创建一个新的JVM;这不使用java可执行文件,因此不容易看到,但它实际上是一个 JVM,就像来自java

  2. 使用该 JVM 运行一些预定义的 Java 代码,这些代码以前位于 JDK/lib/tools.jar 中;在新的 8 后调制 Java 中,我没有费心去追踪它的位置(以及如何访问它)

  3. Java 代码在jinfoJVM 中运行时附加到指定的其他JVM 并访问其中的信息,该 JVM 之前创建和配置java -Xvarious用于运行您的应用程序

您实际上可以自己执行第 2 步和第 3 步;您可以编写使用 API 附加到指定(或以其他方式定位)现有 JVM 并获取所需信息的 Java 代码,并用于java在 JVM#2 中运行访问现有 JVM#1 中信息的代码。但是为什么要麻烦,什么时候jinfojstat jmap jconsole等等)已经做了需要的事情?

就此而言,jps它也是这样做的——它运行自己的 JVM 来运行 Java“工具”代码,该代码使用附加 API 来列出 JVM。这就是由 生成的列表(jps除非经过过滤)包含jps自身的原因。事实上,如果您可以jps在很短的时间jinfo内运行,那么该jps列表还将包括jinfo-- 并且如果您可以在很短的时间内确定 pidjpsjinfo在该 pidjps上运行,您可以获得jinfo-type 信息jpsJVM 。

够清楚吗?

于 2022-01-28T06:13:33.973 回答