Reputation: 6704
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.
Upvotes: 431
Views: 372519
Reputation: 4704
For JDK < 9 on Linux:
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.NoSuchFileException;
public static int getPid() {
try {
return Integer.parseInt(Files.readSymbolicLink(Paths.get("/proc/self")).toString());
} catch (NoSuchFileException e) {
return -1;
} catch (NumberFormatException e) {
return -1;
} catch (IOException e) {
return -1;
}
}
You don't need to parse the text-formatted /proc/self/stat
, just use the syscall:readlink and the procfs implementation.
Upvotes: 0
Reputation: 39536
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());
Upvotes: 28
Reputation: 35404
With Java 10, to get process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Upvotes: 8
Reputation: 7277
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.
Upvotes: 2
Reputation: 9735
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();
Upvotes: 432
Reputation: 2208
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();
}
Upvotes: 36
Reputation: 1360
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();
}
Upvotes: 0
Reputation: 16605
You could use JNA. Unfortunately there is no common JNA API to get the current process ID yet, but each platform is pretty simple:
Make sure you have jna-platform.jar
then:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Declare:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
Then:
int pid = CLibrary.INSTANCE.getpid();
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();
Upvotes: 137
Reputation:
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";
}
Upvotes: 25
Reputation: 2613
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:
tool.jar
is a library distributed with Oracle JDK but not JRE! tool.jar
from Maven repo; configure it with Maven is a bit trickytool.jar
probably contains platform dependent (native?) code so it is not easily
distributableUPDATE: 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:
Upvotes: 4
Reputation: 3183
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
Upvotes: 12
Reputation: 15755
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;
}
Upvotes: 7
Reputation: 2294
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.
Upvotes: 9
Reputation: 198
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.)
Upvotes: 10
Reputation: 55
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;
}
Upvotes: -1
Reputation: 81
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
Upvotes: 2
Reputation: 11858
You can try getpid()
in JNR-Posix.
It has a Windows POSIX wrapper that calls getpid() off of libc.
Upvotes: 1
Reputation: 326
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
Upvotes: -6
Reputation: 27886
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);
Upvotes: 63
Reputation: 51
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
.
Upvotes: 5
Reputation: 1885
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.
Upvotes: 30
Reputation: 189
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)
Upvotes: 18
Reputation: 6611
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.
Upvotes: 4