如何获取Java进程的id?
我知道有几个依赖于平台的技巧,但我更喜欢一个更通用的解决方案。
如何获取Java进程的id?
我知道有几个依赖于平台的技巧,但我更喜欢一个更通用的解决方案。
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.
在linux+windows上,它返回一个值,如<code>“12345@hostname“(1234
是进程id)。不过要小心根据文档,无法保证此值:
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.
在Java 9中新的可以使用过程API:
long pid = ProcessHandle.current().pid();
您可以使用JNA。不幸的是,目前还没有通用的JNA API来获取当前进程ID,但每个平台都很简单:
确保您有jna平台.jar
,然后:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
声明:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
然后:
int pid = CLibrary.INSTANCE.getpid();
在Java 9下,新的进程API可用于获取当前进程ID。首先获取当前进程的句柄,然后查询PID:
long pid = ProcessHandle.current().pid();
这里有一个后门方法,可能不适用于所有虚拟机,但应该同时适用于linux和windows(此处的原始示例):
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);
尝试Sigar。非常广泛的API。Apache 2许可证。
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();
}
以下方法尝试从<code>java.lang.management.ManagementFactory</code>中提取PID:
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;
}
例如,只需调用getProcessId(“<;PID>;”)
。
对于较旧的JVM,在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";
}
自从Java 9以来,有一个方法Process.getPid(),它返回进程的本地ID:
public abstract class Process {
...
public long getPid();
}
要获取当前Java进程的进程ID,可以使用ProcessHandle
接口:
System.out.println(ProcessHandle.current().pid());
您可以查看我的项目:JavaSysMon在GitHub上。它提供跨平台(目前是Windows、Mac OSX、Linux和Solaris)的进程id和一系列其他内容(CPU使用情况、内存使用情况)
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
在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.)
为了完整起见,Spring Boot中有一个包装器,用于
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
解决方案如果需要一个整数,那么这可以归结为一行:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
如果有人已经使用Spring boot,她/他可能会使用org.springframework.boot.ApplicationPid
ApplicationPid pid = new ApplicationPid();
pid.toString();
toString()方法打印pid或。
在其他答案中已经讨论了使用ManagementFactory的注意事项。
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;
}
除了其他解决方案之外,我还添加了这个。
process id
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is " + pid);
我发现的最新情况是,有一个系统属性,名为sun.java。launcher.pid
,至少在linux上可用。我的计划是使用它,如果找不到它,就使用JMXbean
。
这取决于你从哪里寻找信息。
如果您正在从控制台中查找信息,则可以使用jps命令。该命令提供类似于Unix ps命令的输出,并且随JDK一起提供,因为我相信1.5
如果你从流程来看,RuntimeMXBean(正如Wouter Coekaerts所说)可能是你的最佳选择。在使用Sun JDK 1.6 u7的Windows上,getName()的输出形式为[PROCESS_ID]@[MACHINE_NAME]。然而,您可以尝试执行jps并解析其结果:
String jps = [JDK HOME] + "\bin\jps.exe";
Process p = Runtime.getRuntime().exec(jps);
如果在没有选项的情况下运行,则输出应该是进程id后面跟着名称。
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;
}
}
有几个陷阱:
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:
我知道这是一个旧线程,但我想调用用于获取PID的API(以及在运行时对Java进程的其他操作),该API正在被添加到JDK 9中的process类中:http://openjdk.java.net/jeps/102
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();
尽管它不适用于所有平台,但它确实适用于Linux、Windows、OS X和此处列出的各种Unix平台。
您可以在getpid()https://github.com/jnr/jnr-posix“rel=”nofollow“>JNR Posix。
它有一个Windows POSIX包装器,可以从libc中调用getpid()。
我发现了一个可能有点边缘化的解决方案,我没有在Windows 10以外的其他操作系统上尝试过,但我认为这值得注意。
如果您发现自己在使用J2V8和nodejs,您可以运行一个简单的javascript函数,返回java进程的pid。
以下是一个示例:
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;
");
System.out.println(pid);
nodeJS.release();
}
这是我的解决方案:
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
");
return true;
}
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
return false;
}