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 -versioncreates 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} pidattaches 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).jpslists 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.
javaby itself creates a new JVM, separate from any existing one. Normally this JVM runs a user-specified program, but with-versionas 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
jinfodoes in more detail is:create a new JVM; this doesn't use the
javaexecutable, so it isn't easily visible, but it actually is a JVM just like one fromjavause 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
jinfoJVM attaches to, and accesses information in, the specified other JVM, which was previously created and configured withjava -Xvariousto 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
javato run in JVM#2 your code that accesses info in existing JVM#1. But why bother, whenjinfo(andjstat jmap jconsoleetc) already does what is needed?For that matter,
jpsalso 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, includesjpsitself. In fact, if you could runjpsduring the very short timejinfois running, thejpslist would includejinfoalso -- and if you could determine the pid forjpsand runjinfoon that pid during the very short timejpsis running, you could getjinfo-type information on thejpsJVM.Clear enough?