How to get Process ID for any JVM application? How to get PID for current process?
There is plenty of solutions on Stackoverflow, mostly involving operating system hacks [1], or libraries with native code [2] or
I would like to introduce another solution, JConsole, and potentially jps and VisualVM uses. It is based on classes from
There is plenty of solutions on Stackoverflow, mostly involving operating system hacks [1], or libraries with native code [2] or
ManagementFactory.getRuntimeMXBean()
based solutions [3], limited to current process only.I would like to introduce another solution, JConsole, and potentially jps and VisualVM uses. It is based on classes from
sun.jvmstat.monitor.*
package, from tool.jar
.Jvmstat solution
This simple program gets list of all running JVMs on localhost, with their PIDs, and then extracting their main their classes comparing them to given main class name, returning PID when they match.
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
public class GetOwnPid {
public static void main(String[] args) {
new GetOwnPid().run();
}
public void run() {
System.out.println(getPid(this.getClass()));
}
public Integer getPid(Class<?> mainClass) {
MonitoredHost monitoredHost;
Set<Integer> activeVmPids;
try {
monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
activeVmPids = monitoredHost.activeVms();
MonitoredVm mvm = null;
for (Integer vmPid : activeVmPids) {
try {
mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
String mvmMainClass = MonitoredVmUtil.mainClass(mvm, true);
if (mainClass.getName().equals(mvmMainClass)) {
return vmPid;
}
} finally {
if (mvm != null) {
mvm.detach();
}
}
}
} catch (java.net.URISyntaxException e) {
throw new InternalError(e.getMessage());
} catch (MonitorException e) {
throw new InternalError(e.getMessage());
}
return null;
}
}
There are few catches:
- The
tool.jar
is a library distributed with Oracle JDK but not JRE! - You cannot get
tool.jar
from Maven repo; configure it with Maven is a bit tricky, see [6]. - The
tool.jar
probably contains platform dependent (native?) code so it is not easily distributable - It runs under assumption that all (local) running JVM apps are "monitorable". It looks like that from Java 6 all apps generally are (unless you actively configure opposite)
- It probably works only for Java 6+
- Eclipse does not publish main class, so you will not get Eclipse PID easily. It is probably because Eclipse is a JVM application, but is launched as eclipse.exe, a native executable somehow encapsulating JVM. You yould have to employ more sophisticated measures, like VisualVM does, to recognize Eclipse like checking characteristic JVM properties.
Comments on another questionable but popular solution
There is one more popular solution, mentioned for example here [4], and that is to use Process implementation class and get PID from its internal private data.
Process process = Runtime.getRuntime().exec(command);
and then check returned implementation; allegedly on Unix it is java.lang.UnixProcess
which has a private field called pid. But on Windows Process implementation returned is java.lang.ProcessImpl
and it has no such field, no notion of PID. This is not a cross platform solution, besides relying on forcefully accessed private fields is always hackish and can stop working in the next Java release.