I restarted a Java process with new memory options -Xms4G -Xmx4G -XX:MaxDirectMemorySize=6G
and wanted to verify if these changes got correctly applied, especially the 6G of direct memory.
The first solution I found for verifying this was via java
itself, but this simply reported a 0
, implying that my new settings had no effect:
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)
A second solution I found later was via jinfo
, which apparently confirm the 6G
that I indended to set:
bash-4.4$ jinfo -flag MaxDirectMemorySize 1
-XX:MaxDirectMemorySize=6442450944
I've relied on the java -XX:+PrintFlagsFinal
for other purposes before, but now I wonder why it doesn't return the expected values. Why are java
and jinfo
returning different results?
There's (at least) two different JVMs.
[Expanding comment:]
java {nothing} -XX:+PrintFlagsFinal -version
creates a new JVM, changes none of its configuration from the default, and prints the resulting configuration, which is the default configuration with no changes -- and the default for MaxDirectMemSize is indeed zero.OTOH
jinfo {option} pid
attaches to an existing already running JVM and obtains or changes the configuration of that JVM (although the specific pid 1 isn't usually a JVM but it often is in a docker container as you are using).jps
lists the running JVMs you can attach to, with options to include JVM arguments and/or application arguments.Yes and no; it gets a bit Wonderlandy.
java
by itself creates a new JVM, separate from any existing one. Normally this JVM runs a user-specified program, but with-version
as you used it just prints version info and exits without running anything.Now, the attach API is accessible from (and actually written partly in) Java. What
jinfo
does in more detail is:create a new JVM; this doesn't use the
java
executable, so it isn't easily visible, but it actually is a JVM just like one fromjava
use that JVM to run some predefined Java code, which used to be in JDK/lib/tools.jar; I haven't bothered to track down where it is (and exactly how to access it) in the new post-8 modulated Java
that Java code when run in the
jinfo
JVM attaches to, and accesses information in, the specified other JVM, which was previously created and configured withjava -Xvarious
to run your applicationYou can actually do steps 2 and 3 yourself; you could write Java code that uses the API to attach to a specified (or otherwise located) existing JVM and get the info you want, and use
java
to run in JVM#2 your code that accesses info in existing JVM#1. But why bother, whenjinfo
(andjstat jmap jconsole
etc) already does what is needed?For that matter,
jps
also does this -- it runs its own JVM to run Java 'tool' code that uses the attach API to list JVMs. That's why the list produced byjps
, unless filtered, includesjps
itself. In fact, if you could runjps
during the very short timejinfo
is running, thejps
list would includejinfo
also -- and if you could determine the pid forjps
and runjinfo
on that pid during the very short timejps
is running, you could getjinfo
-type information on thejps
JVM.Clear enough?