How can a Java program get its own process ID?
Solution 1
There exists no platform-independent way that can be guaranteed to work in all jvm implementations.
ManagementFactory.getRuntimeMXBean().getName()
looks like the best (closest) solution, and typically includes the PID. It's short, and probably works in every implementation in wide use.
On linux+windows it returns a value like "12345@hostname"
(12345
being the process id). Beware though that according to the docs, there are no guarantees about this value:
Returns the name representing the running Java virtual machine. The returned name string can be any arbitrary string and a Java virtual machine implementation can choose to embed platform-specific useful information in the returned name string. Each running virtual machine could have a different name.
In Java 9 the new process API can be used:
long pid = ProcessHandle.current().pid();
Solution 2
You could use JNA. Unfortunately there is no common JNA API to get the current process ID yet, but each platform is pretty simple:
Windows
Make sure you have jna-platform.jar
then:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Unix
Declare:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Then:
int pid = CLibrary.INSTANCE.getpid();
Java 9
Under Java 9 the new process API can be used to get the current process ID. First you grab a handle to the current process, then query the PID:
long pid = ProcessHandle.current().pid();
Solution 3
Here's a backdoor method which might not work with all VMs but should work on both linux and windows (original example here):
java.lang.management.RuntimeMXBean runtime =
java.lang.management.ManagementFactory.getRuntimeMXBean();
java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
jvm.setAccessible(true);
sun.management.VMManagement mgmt =
(sun.management.VMManagement) jvm.get(runtime);
java.lang.reflect.Method pid_method =
mgmt.getClass().getDeclaredMethod("getProcessId");
pid_method.setAccessible(true);
int pid = (Integer) pid_method.invoke(mgmt);
Solution 4
Try Sigar . very extensive APIs. Apache 2 license.
private Sigar sigar;
public synchronized Sigar getSigar() {
if (sigar == null) {
sigar = new Sigar();
}
return sigar;
}
public synchronized void forceRelease() {
if (sigar != null) {
sigar.close();
sigar = null;
}
}
public long getPid() {
return getSigar().getPid();
}
Solution 5
The following method tries to extract the PID from java.lang.management.ManagementFactory
:
private static String getProcessId(final String fallback) {
// Note: may fail in some JVM implementations
// therefore fallback has to be provided
// something like '<pid>@<hostname>', at least in SUN / Oracle JVMs
final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
final int index = jvmName.indexOf('@');
if (index < 1) {
// part before '@' empty (index = 0) / '@' not found (index = -1)
return fallback;
}
try {
return Long.toString(Long.parseLong(jvmName.substring(0, index)));
} catch (NumberFormatException e) {
// ignore
}
return fallback;
}
Just call getProcessId("<PID>")
, for instance.
Comments
-
Steve almost 2 years
How do I get the id of my Java process?
I know there are several platform-dependent hacks, but I would prefer a more generic solution.
-
Brad Mace over 11 yearsYou'd have a lot more upvotes if you explained how to use SIGAR for this
-
Drupad Panchal over 11 yearsvery nice, just verified that it works both on the JRockit as well as the Hotspot JVMs.
-
ATorras about 11 years+1 But I'm afraid that in a security constrained environment it should not work (tomcat, WebLogic, etc.).
-
Espinosa almost 11 yearsVisualVM uses similar code to get self PID, check com.sun.tools.visualvm.application.jvm.Jvm#ApplicationSupport#createCurrentApplication(). They are the experts, so it looks like dependable, cross platform solution.
-
Espinosa almost 11 yearsJPS tool uses jvmstat library, part of tools.jar. Check my example or see JPS source code: grepcode.com/file_/repository.grepcode.com/java/root/jdk/…. There is no need to call JPS as external process, use jvmstat library directly.
-
fragorl about 10 yearsNice workaround. I'm going to assume there is a good reason why this method (and others in the class) aren't public and easily accessible, and I'm curious to know what it is.
-
Michael Klishin about 10 yearsThis solution is really fragile. See an answer about Hyperic Sigar below.
-
Rich about 10 yearsIf you're calling shell scripts, you might as well do something simpler like
bash -c 'echo $PPID'
or the /proc answers above -
hfontanez over 9 yearsOracle Java team have announced that they intend to hide all non-java packages (i.e. sun.*) I believe starting with Java 10 (scheduled for 2018 - maybe Java 9). If you have a similar implementation as the one above, you may want to figure out an alternative so that your code don't break.
-
Aquarius Power about 9 yearsthat pid is good to write on a lock file as stackoverflow.com/a/9020391/1422630
-
Steve almost 9 yearsWow, that was fast. It only took about seven years! 😃
-
Augusto over 8 yearsCan you explain how to get a Process instance for the current running process in Java 9?
-
Mike Stoddart over 8 yearsDoesn't work for me either as the sun.* packages are probably removed or inaccessible (VMManagement cannot be resolved to a type).
-
crazyGuy about 8 yearsGreat answer for using Java 9 in 2016! Can you add a link to the javadocs? thanks
-
Daniel Widdis almost 8 yearsThe
getpid()
solution also works for OS X, with a JNA call to the "System" library. -
Panayotis almost 8 yearsIs it possible to get the PID of a Process started by Java? Or start a Process "your way" to fix this issue?
-
c0der over 7 yearsThis does not check if pid is in use, but if pid equals current process pid
-
PartialData over 7 yearsWhat is the correct solution so i can update my code?
-
Narendra Parmar over 7 yearsif mainClass.getName() does not work try to use mainClass.getCanonicalName();
-
david.perez about 7 yearsIn my case with Ubuntu 16.04 and Java 8, it returns null
-
Jules over 6 yearsLink is broken. You give an example of how to use this, but is there a maven dependency for it?
-
skytree over 6 yearsHowever, I get
error: cannot find symbol
for jdk9 -
Zastai over 5 yearsgithub.com/hyperic/sigar seems to be a usable location; this also shows that it's native code with Java bindings, which may make it less of a solution for many contexts.
-
Andrew T Finnell about 5 yearsDue to the way reflection works, access to sun.management.* is not needed. Just perform the
getDeclaredMethod
on the Object returned byjvm.get(runtime)
. -
matbrgz about 4 years@Espinosa VisualVM only supportes running on a OpenJDK/Oracle/GraalVM JVM (as of 2020). This mean they can make assumptions accordingly. If you do the same, you become vendor dependent and your code may break if running on for instance J9.
-
Seth Tisue over 3 years(looks good for Linux and macOS, but I don't know if it would work on Windows)
-
toolforger almost 2 yearsStarting an entire new subprocess just to get the PID which is already available in the process itself is pretty overblown. Also, this won't work on Windows since it has no "sh" command (usually).