Java程序如何获得自己的进程ID?

Dmi*_*man 334 java pid

如何获取Java进程的ID?

我知道有几个依赖于平台的黑客,但我更喜欢更通用的解决方案.

Wou*_*rts 313

没有平台无关的方式可以保证在所有jvm实现中都能工作. ManagementFactory.getRuntimeMXBean().getName()看起来像最好(最接近)的解决方案.它很简短,可能适用于广泛使用的每个实现.

在linux + windows上,它返回一个像12345@hostname(12345作为进程id)的值.请注意,根据文档,不保证这个值:

返回表示正在运行的Java虚拟机的名称.返回的名称字符串可以是任意字符串,Java虚拟机实现可以选择在返回的名称字符串中嵌入特定于平台的有用信息.每个正在运行的虚拟机可以具有不同的名称.

在Java 9中,可以使用新的流程API:

long pid = ProcessHandle.current().pid();
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案非常脆弱.请在下面看到关于Hyperic Sigar的答案. (2认同)
  • @MichaelKlishin 在哪方面那么脆弱? (2认同)

Luk*_*ane 109

你可以使用JNA.遗憾的是,目前没有通用的JNA API来获取当前的进程ID,但每个平台都非常简单:

视窗

确保你有jna-platform.jar:

int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Run Code Online (Sandbox Code Playgroud)

Unix的

宣布:

private interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);   
    int getpid ();
}
Run Code Online (Sandbox Code Playgroud)

然后:

int pid = CLibrary.INSTANCE.getpid();
Run Code Online (Sandbox Code Playgroud)

Java 9

在Java 9下,新的流程API可用于获取当前进程ID.首先,您获取当前进程的句柄,然后查询PID:

long pid = ProcessHandle.current().pid();
Run Code Online (Sandbox Code Playgroud)

  • +1但我担心在安全受限的环境中它不应该工作(tomcat,WebLogic等). (4认同)

Bra*_*ace 56

这是一个后门方法,它可能不适用于所有虚拟机,但应该适用于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);
Run Code Online (Sandbox Code Playgroud)

  • 适用于1.7 ..不适用于1.8:| (5认同)
  • 非常好,只是验证它在JRockit和Hotspot JVM上都有效. (2认同)
  • Oracle Java团队宣布他们打算隐藏所有非java软件包(即sun.*).我相信从Java 10开始(计划于2018年 - 也许是Java 9).如果您具有与上面类似的实现,您可能想要找出一个替代方案,以便您的代码不会中断. (2认同)

Ash*_*ash 36

试试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();
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果您解释*如何*为此使用SIGAR,您会有更多的赞成 (5认同)
  • https://github.com/hyperic/sigar 似乎是一个可用的位置;这也表明它是具有 Java 绑定的本机代码,这可能使其不太适合许多上下文的解决方案。 (3认同)

Mar*_*tin 26

以下方法尝试从以下位置提取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 '<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;
}
Run Code Online (Sandbox Code Playgroud)

getProcessId("<PID>")例如,请致电.

  • VisualVM使用类似的代码来获取自身PID,请检查com.sun.tools.visualvm.application.jvm.Jvm#ApplicationSupport #createCurrentApplication().他们是专家,因此它看起来像可靠的跨平台解决方案. (6认同)

小智 22

对于较旧的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";
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你要这样做,那就做`int pid = Integer.parseInt(new File("/ proc/self").getCanonicalFile().getName());`.为什么额外的旋转? (50认同)
  • getCanonicalFile()解析符号链接/ proc/self/ - >/proc/1234,试试ls -al/proc/self (7认同)
  • 对于好奇,@ David的评论中的诀窍实际上是有效的.有人可以说为什么?`getCanonicalFile()`方法中的某种魔法将"self"转换为PID? (2认同)
  • @DavidCitron +1!你是对的,我没想到getCanonicalFile :-) (2认同)

小智 18

你可以看看我的项目:GitHub上的JavaSysMon.它提供了进程ID和一堆其他东西(CPU使用,内存使用)跨平台(目前是Windows,Mac OSX,Linux和Solaris)


Zhe*_*lov 16

从Java 9开始,有一个方法Process.getPid(),它返回进程的本机ID:

public abstract class Process {

    ...

    public long getPid();
}
Run Code Online (Sandbox Code Playgroud)

要获取当前Java进程的进程ID,可以使用该ProcessHandle接口:

System.out.println(ProcessHandle.current().pid());
Run Code Online (Sandbox Code Playgroud)

  • 您能解释一下如何在Java 9中获取当前运行进程的Process实例吗? (2认同)

Flo*_* T. 7

在斯卡拉:

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

这将为您提供Unix系统的解决方法,直到Java 9发布.(我知道,这个问题是关于Java的,但是由于Scala没有相同的问题,我想把它留给可能会遇到同样问题的Scala用户.)


l00*_*0tr 7

为了完整存在的包装春天启动

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];
Run Code Online (Sandbox Code Playgroud)

解.如果需要一个整数,那么这可以总结为一行:

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
Run Code Online (Sandbox Code Playgroud)

如果有人使用Spring启动,她/他可能会使用org.springframework.boot.ApplicationPid

ApplicationPid pid = new ApplicationPid();
pid.toString();
Run Code Online (Sandbox Code Playgroud)

toString()方法打印pid或'???'.

使用ManagementFactory的注意事项已在其他答案中讨论.


Jas*_*key 6

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;
}
Run Code Online (Sandbox Code Playgroud)


mar*_*kus 6

java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
Run Code Online (Sandbox Code Playgroud)


小智 5

我发现最新的是,有一个系统属性名为sun.java.launcher.pid可用至少在Linux上.我的计划是使用它,如果没有找到使用它JMX bean.


mrs*_*vas 5

除了其他解决方案之外,我还要添加这个。

使用 Java 10,得到 process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
Run Code Online (Sandbox Code Playgroud)