How can a Java program get its own process ID?
Asked Answered
S

22

428

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.

Sculley answered 30/8, 2008 at 9:53 Comment(4)
A link to a Linux question: How do I find my PID in Java or JRuby on Linux?Silvana
This is meant to be fixed in JDK9. openjdk.java.net/jeps/102Preparation
Way to do it in Java SE10Nazler
Another way is to create a JNI library.Trembly
M
422

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();
Manipulator answered 30/8, 2008 at 11:11 Comment(3)
This solution is really fragile. See an answer about Hyperic Sigar below.Heller
that pid is good to write on a lock file as https://mcmap.net/q/82045/-how-can-i-lock-a-file-using-java-if-possibleCodicodices
@MichaelKlishin in what regard is that fragile?Gourde
S
132

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();
Slabber answered 5/9, 2011 at 2:33 Comment(3)
+1 But I'm afraid that in a security constrained environment it should not work (tomcat, WebLogic, etc.).Figureground
The getpid() solution also works for OS X, with a JNA call to the "System" library.Rigel
However, I get error: cannot find symbol for jdk9Arch
R
63

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);
Retreat answered 22/8, 2012 at 5:19 Comment(5)
very nice, just verified that it works both on the JRockit as well as the Hotspot JVMs.Overt
Nice 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.Tso
Oracle 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.Sprightly
Doesn't work for me either as the sun.* packages are probably removed or inaccessible (VMManagement cannot be resolved to a type).Clinker
Due to the way reflection works, access to sun.management.* is not needed. Just perform the getDeclaredMethod on the Object returned by jvm.get(runtime).Package
S
36

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();
}
Strip answered 28/6, 2010 at 18:9 Comment(4)
You'd have a lot more upvotes if you explained how to use SIGAR for thisRetreat
Link is broken. You give an example of how to use this, but is there a maven dependency for it?Lailalain
github.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.Handspike
Sigar doesn't work on Apple SiliconKatinka
M
30

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.

Multiversity answered 7/10, 2011 at 16:32 Comment(2)
VisualVM 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.Shinleaf
@Shinleaf 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.Weig
H
25

For older JVM, in linux...

private static String getPid() throws IOException {
    byte[] bo = new byte[256];
    InputStream is = new FileInputStream("/proc/self/stat");
    is.read(bo);
    for (int i = 0; i < bo.length; i++) {
        if ((bo[i] < '0') || (bo[i] > '9')) {
            return new String(bo, 0, i);
        }
    }
    return "-1";
}
Hindmost answered 16/6, 2011 at 12:56 Comment(4)
If you're going to do that, then just do int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());. Why the extra gyrations?Slaveholder
For the curious, the trick in @David 's comment actually works. Can someone say why? Some sort of magic in the getCanonicalFile() method that converts "self" to the PID?Hebetate
getCanonicalFile() resolves the symlink /proc/self/ -> /proc/1234, try ls -al /proc/selfVercelli
@DavidCitron +1! you are right, I did not think in getCanonicalFile :-)Yeomanry
D
24

Since Java 9 there is a method Process.pid() which returns the native ID of a process:

public abstract class Process {

    ...

    public long pid();
}

To get the process ID of the current Java process one can use the ProcessHandle interface:

System.out.println(ProcessHandle.current().pid());
Dubai answered 26/6, 2015 at 11:56 Comment(2)
Can you explain how to get a Process instance for the current running process in Java 9?Linotype
Great answer for using Java 9 in 2016! Can you add a link to the javadocs? thanksNarbonne
I
18

You can check out my project: JavaSysMon on GitHub. It provides process id and a bunch of other stuff (CPU usage, memory usage) cross-platform (presently Windows, Mac OSX, Linux and Solaris)

Indoor answered 26/12, 2009 at 0:44 Comment(1)
Is it possible to get the PID of a Process started by Java? Or start a Process "your way" to fix this issue?Whippet
L
12
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
Luciferous answered 13/4, 2017 at 19:9 Comment(0)
V
10

In Scala:

import sys.process._
val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong

This should give you a workaround on Unix systems until Java 9 will be released. (I know, the question was about Java, but since there is no equivalent question for Scala, I wanted to leave this for Scala users who might stumble into the same question.)

Vamoose answered 20/11, 2015 at 23:32 Comment(2)
(looks good for Linux and macOS, but I don't know if it would work on Windows)Deathwatch
Starting 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).Readytowear
A
9

For completeness there is a wrapper in Spring Boot for the

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];

solution. If an integer is required, then this can be summed up to the one-liner:

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

If someone uses Spring boot already, she/he might use org.springframework.boot.ApplicationPid

ApplicationPid pid = new ApplicationPid();
pid.toString();

The toString() method prints the pid or '???'.

Caveats using the ManagementFactory are discussed in other answers already.

Alee answered 30/6, 2016 at 12:20 Comment(0)
F
7
public static long getPID() {
    String processName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
    if (processName != null && processName.length() > 0) {
        try {
            return Long.parseLong(processName.split("@")[0]);
        }
        catch (Exception e) {
            return 0;
        }
    }

    return 0;
}
Flagellate answered 28/9, 2016 at 10:14 Comment(0)
N
7

With Java 10, to get process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Nazler answered 24/2, 2018 at 3:50 Comment(0)
P
5

The latest I have found is that there is a system property called sun.java.launcher.pid that is available at least on linux. My plan is to use that and if it is not found to use the JMX bean.

Porringer answered 5/9, 2011 at 13:47 Comment(1)
In my case with Ubuntu 16.04 and Java 8, it returns nullMarinna
D
4

It depends on where you are looking for the information from.

If you are looking for the information from the console you can use the jps command. The command gives output similar to the Unix ps command and comes with the JDK since I believe 1.5

If you are looking from the process the RuntimeMXBean (as said by Wouter Coekaerts) is probably your best choice. The output from getName() on Windows using Sun JDK 1.6 u7 is in the form [PROCESS_ID]@[MACHINE_NAME]. You could however try to execute jps and parse the result from that:

String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);

If run with no options the output should be the process id followed by the name.

Devilkin answered 4/9, 2008 at 1:7 Comment(1)
JPS 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.Shinleaf
S
4

This is the code JConsole, and potentially jps and VisualVM uses. It utilizes classes from sun.jvmstat.monitor.* package, from tool.jar.

package my.code.a003.process;

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
  • 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 Bug in MonitoredVmUtil?

UPDATE: I have just double checked that JPS uses this way, that is Jvmstat library (part of tool.jar). So there is no need to call JPS as external process, call Jvmstat library directly as my example shows. You can aslo get list of all JVMs runnin on localhost this way. See JPS source code:

Shinleaf answered 27/6, 2013 at 16:28 Comment(1)
if mainClass.getName() does not work try to use mainClass.getCanonicalName();Bane
H
2

Based on Ashwin Jayaprakash's answer (+1) about the Apache 2.0 licensed SIGAR, here is how I use it to get only the PID of the current process:

import org.hyperic.sigar.Sigar;

Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();

Even though it does not work on all platforms, it does work on Linux, Windows, OS X and various Unix platforms as listed here.

Hibbard answered 11/2, 2014 at 12:47 Comment(0)
C
2

I know this is an old thread, but I wanted to call out that API for getting the PID (as well as other manipulation of the Java process at runtime) is being added to the Process class in JDK 9: http://openjdk.java.net/jeps/102

Conciliator answered 24/6, 2015 at 21:7 Comment(1)
Wow, that was fast. It only took about seven years! 😃Sculley
E
1

You can try getpid() in JNR-Posix.

It has a Windows POSIX wrapper that calls getpid() off of libc.

Electrical answered 11/3, 2015 at 8:15 Comment(0)
L
0

I found a solution that may be a bit of an edge case and I didn't try it on other OS than Windows 10, but I think it's worth noticing.

If you find yourself working with J2V8 and nodejs, you can run a simple javascript function returning you the pid of the java process.

Here is an example:

public static void main(String[] args) {
    NodeJS nodeJS = NodeJS.createNodeJS();
    int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
    System.out.println(pid);
    nodeJS.release();
}
Loudspeaker answered 1/9, 2018 at 17:57 Comment(0)
T
-1

Here is my solution:

public static boolean isPIDInUse(int pid) {

        try {

            String s = null;
            int java_pid;

            RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
            java_pid = Integer.parseInt(rt.getName().substring(0, rt.getName().indexOf("@")));

            if (java_pid == pid) {
                System.out.println("In Use\n");
                return true;
            }
        } catch (Exception e) {
            System.out.println("Exception:  " + e.getMessage());
        }
        return false;
    }
Timmerman answered 6/11, 2015 at 19:10 Comment(2)
This does not check if pid is in use, but if pid equals current process pidAna
What is the correct solution so i can update my code?Timmerman
P
-6

This is what I used when I had similar requirement. This determines the PID of the Java process correctly. Let your java code spawn a server on a pre-defined port number and then execute OS commands to find out the PID listening on the port. For Linux

netstat -tupln | grep portNumber
Piccaninny answered 30/9, 2013 at 9:42 Comment(1)
If you're calling shell scripts, you might as well do something simpler like bash -c 'echo $PPID' or the /proc answers aboveHearsay

© 2022 - 2024 — McMap. All rights reserved.