Summary
-------
Add `jcmd <pid> VM.usage_metadata` to print metadata describing the JVM invocation.
Problem
-------
Many monitoring and observability agent(s) (and other such tools) want to obtain metadata from JVMs that describes how they were configured and invoked, e.g:
- JVM version class and/or module path
- JAVA_HOME
- any JVM flags specified
- any JVM arguments specified
- program arguments
- JVM start time
- JVM uptime
- if executing in the context of a "resource manager" (Docker etc)
- ...
in order to obtain such, these agent(s) must currently invoke multiple `jcmd`'s, if such exists.
This is not optimal for a variety of reasons.
Solution
--------
Add a new command that the `jcmd` command line tool can use to print metadata about JVM usage.
The output is formatted (either in plain text or as JSON) as a list of key,value tuples.
The command effectively treats the individual metadata "fields" as `System` property names, and where none exist for particular metadata (such as JVM uptime) a "synthetic" property (name) is used in order to uniquely name such metadata.
Here is example (default) output (the output is JSON encoded to enable programmatic parsing).
[Note: fields are shown on a separate line for clarity, the implementation does not reflect this in order to facilitate log append style of collection]
```
135986:
{
"timestamp" : "2024-09-10T12:06:02.953-0700",
"jvm.starttime" : "2024-09-10T19:05:41.976+0000",
"java.home" : "/home/auser/src/git/jdk/open/build/linux-x86_64-server-release/jdk",
"java.version" : "24-internal",
"java.vm.version" : "24-internal-adhoc.lpgc.open",
"sun.java.launcher" : "SUN_STANDARD",
"jvm.args" : [ "-Dapplication.home=/home/auser/src/git/jdk/open/build/linux-x86_64-server-release/jdk", "-Xms8m", "-Djdk.module.main=jdk.jshell" ],
"sun.java.command" : "jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider",
"java.class.path" : "",
"jvm.pid" : "135986",
"jvm.uptime.ms" : "21123",
"os.name" : "Linux",
"os.version" : "4.18.0-553.16.1.el8_10.x86_64",
"os.arch" : "amd64"
"os.hostname" : "ahost"
}
```
an example of plain text is:
```
135986:
"timestamp"="2024-09-10T12:26:17.478-0700",
"jvm.starttime"="2024-09-10T19:05:41.976+0000",
"java.home"="/home/auser/src/git/jdk/open/build/linux-x86_64-server-release/jdk",
"java.version"="24-internal",
"java.vm.version"="24-internal-adhoc.auser.open",
"sun.java.launcher"="SUN_STANDARD",
"jvm.args"="'-Dapplication.home=/home/auser/src/git/jdk/open/build/linux-x86_64-server-release/jdk', '-Xms8m', '-Djdk.module.main=jdk.jshell'",
"sun.java.command"="jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider",
"java.class.path"="",
"jvm.pid"="135986",
"jvm.uptime.ms"="1235648",
"os.name"="Linux",
"os.version"="4.18.0-553.16.1.el8_10.x86_64",
"os.arch"="amd64"
"os.hostname"="ahost"
```
Specification
-------------
The man page `jcmd(1)` describes this new `jcmd` as:
`VM.usage_metadata [options]`
Print VM usage metadata as a formatted list of key & (non null) value tuples.
Impact: Low
Note:
The following options must be specified using either key or key=value syntax.
options:
- `-omitIfNull`: (Optional) omit fields if they are null valued (BOOLEAN, false)
- `format`: (Optional) Output format ("plain" or "json") (STRING, plain)
- `filename`: (Optional) The file path to the output file into which, append usage metadata (STRING, no default value)
- `fields`: (Optional) a comma separated list of fields (`System` properties, real or synthetic) to print (when non-null) overriding the default (STRING, see below)
Fields are either `System` Property names(c.f: `java.lang.System` for definitions), or certain "synthetic" properties (where there is no pre-existing `System` Property):
- `jvm.args`: any command line arguments specified for the JVM.
- `jvm.container.info`: (Note: these fields are not affected by the omitIfNull flag, they are only present if the JVM detects the presence of resource mgmt - linux only):
- `type` (`cgroupv1` or `cgroupv2)`
- `memory.limit` or -1 for unrestricted
- # of `active.cpus` therein.
- `jvm.flags`: the JVM flags.
- `jvm.pid`: the process id of the JVM.
- `jvm.starttime`: the time when the JVM completed its initialization just prior to commencing execution of user code.
- `jvm.uptime.ms`: the uptime (in ms) of the JVM.
- `os.hostname`: the name of the host machine (or container, when the JVM is executing in that context)
- `timestamp`: the current time.
Note: if the value (comma separated list of property names) of the `fields`. parameter is prefixed with a `+`, then the subsequent list of parameters are appended to the `default` listing, if no `+` is present then the property list overrides the default list.
The default set of fields reported are (in order):
`timestamp`
`jvmstarttime`
` java.home`
`java.version`
`java.vm.version`
`sun.java.launcher`
`jvm.flags`
`jvm.args`
`sun.java.cmd`
`java.classpath`
`jdk.module.path`
`jdk.main.module`
`jdk.main.module.class`
`jdk.upgrade.module.path`
`jvm.pid,jvm.uptime.ms`
`jvm.ctr.info.type`
`jvm.ctr.info.memory.limit`
`jvm.ctr.active.cpus`
`os.hostname`
`os.name`
`os.version`
`os.arch`