Ever wanted to be able to know your process’ PID through pure-Java, cross-platform methods? Or worse, other JVMs?
At my work we came to a point where we needed to monitor and register a JVM’s PID (Linux/Windows/Whatever) for some future manipulation purposes. However, Java in itself did not contain the concept of “process ID” - Even the Process class (which is horrible, for different reasons which might be discussed on a different post) doesn’t have any way of getting that information.
However, JavaVM Process Status Tool (JPS) seems to be written entirely in Java and is actually able to retrieve this information! Jps is a Java class located on Linux and Windows in the jdk/lib/tools.jar file, or in the CurrentJDK/Classes/classes.jar if you’re using a Mac. Also, it’s only bundled with JDK 5 and up, which I assume that by now, all of the readers have installed.
The problem with using the Jps class out of the box (even if undocumented) is that it’s built to a be a command-line tool - It reads parameters from the arguments passed, and prints out to System.out only. The only resort is to understand how it works, and to re-write it to our own needs.
Since the source code is not widely available, a simple disassembling of the Jps code (using JAD) was made, and the following code (modified to make sense) revealed an undocumented class, MonitoredHost:
// passing null connects to the local machine
MonitoredHost host = MonitoredHost.getMonitoredHost(null);
for (Object activeVmPid : host.activeVms()) {
int pid = (Integer)activeVmPid;
// do something with the pid
}
It also revealed another information-abundant class called MonitoredVm, which can be created with the following line:
VmIdentifier vmId = new VmIdentifier("//" + pid + "?mode=r");
MonitoredVm vm = host.getMonitoredVm(vmId, 0);
The amazing thing is that the VM identifier looks like a URL. And what is the mode=r part? Does it mean “read-only”? Back to business: after obtaining the MonitoredVm, information like the command line used to start it, JVM arguments passed to it, the main class it is running, and the VM version can be obtained using the MonitoredVmUtil class.
Also, the MonitoredVm offers to register a listener, VmListener, which listens to different monitors on the VM, apparently. I didn’t get enough time to study it, but I’m sure it can reveal interesting information as well!
July 3rd, 2007 at 1:06 pm
Hello Avah,
Seems there is a typo. Did you mean
MonitoredVm vm = host.getMonitoredVm(vmId , 0); ?
July 3rd, 2007 at 1:18 pm
Whoops!
Thanks! (Fixed!)
September 4th, 2007 at 1:35 pm
Alternatively, ManagementFactory.getRuntimeMXBean().getName() can be used. This returns pid@hostname. Though the returned string is dependent on jvm implemention, it works on bea’s jrockit and sun’s jdk.
I get 5554@, where 5554 is the pid of the jvm.
July 23rd, 2008 at 4:28 pm
For each started Hotspot jvm, a temporary file in /hsperfdata_ is created, which name is actually the process id ( is the value of “java.io.tmpdir” system property).
This file is used by the classes mentioned here to get the process id, and MonitoredVmUtil actually parses this file to extract other useful information (MonitoredVmUtil actually contains some other useful methods : vmVersion(), commandLine(), mainArgs(), mainClass(), jvmArgs() and jvmFlags(), all of them take a MonitoredVm as argument.
This opens a lot of new opportunities.
To Bharath : Using ManagementFactory.getRuntimeMXBean().getName() to get the pid also works on ibm jvm.