如何获取Java进程的ID?
我知道有几个依赖于平台的黑客,但我更喜欢更通用的解决方案.
没有平台无关的方式可以保证在所有jvm实现中都能工作.
ManagementFactory.getRuntimeMXBean().getName()
看起来像最好(最接近)的解决方案.它很简短,可能适用于广泛使用的每个实现.
在linux + windows上,它返回一个像12345@hostname
(12345
作为进程id)的值.请注意,根据文档,不保证这个值:
返回表示正在运行的Java虚拟机的名称.返回的名称字符串可以是任意字符串,Java虚拟机实现可以选择在返回的名称字符串中嵌入特定于平台的有用信息.每个正在运行的虚拟机可以具有不同的名称.
在Java 9中,可以使用新的流程API:
long pid = ProcessHandle.current().pid();
你可以使用JNA.遗憾的是,目前没有通用的JNA API来获取当前的进程ID,但每个平台都非常简单:
确保你有jna-platform.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(); }
以下方法尝试从以下位置提取PID 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 '@ ', 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("
例如,请致电.
对于较旧的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"; }
你可以看看我的项目:GitHub上的JavaSysMon.它提供了进程ID和一堆其他东西(CPU使用,内存使用)跨平台(目前是Windows,Mac OSX,Linux和Solaris)
从Java 9开始,有一个方法Process.getPid(),它返回进程的本机ID:
public abstract class Process { ... public long getPid(); }
要获取当前Java进程的进程ID,可以使用该ProcessHandle
接口:
System.out.println(ProcessHandle.current().pid());
在斯卡拉:
import sys.process._ val pid: Long = Seq("sh", "-c", "echo $PPID").!!.trim.toLong
这将为您提供Unix系统的解决方法,直到Java 9发布.(我知道,这个问题是关于Java的,但是由于Scala没有相同的问题,我想把它留给可能会遇到同样问题的Scala用户.)
为了完整存在的包装春天启动的
String jvmName = ManagementFactory.getRuntimeMXBean().getName(); return jvmName.split("@")[0];
解.如果需要一个整数,那么这可以总结为一行:
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
如果有人使用Spring启动,她/他可能会使用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; }
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
我发现最新的是,有一个系统属性名为sun.java.launcher.pid
可用至少在Linux上.我的计划是使用它,如果没有找到使用它JMX bean
.