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

时间:2008-08-30 09:53:25

标签: java pid

如何获取Java进程的ID?

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

22 个答案:

答案 0 :(得分:301)

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

在linux + windows上,它返回一个类似12345@hostname的值(12345是进程ID)。请注意according to the docs,但不保证这个值:

  

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

在Java 9 中,可以使用新的process API

long pid = ProcessHandle.current().pid();

答案 1 :(得分:107)

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

确保您拥有jna-platform.jar

int pid = Kernel32.INSTANCE.GetCurrentProcessId();

的Unix

宣告:

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

然后:

int pid = CLibrary.INSTANCE.getpid();

Java 9

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

long pid = ProcessHandle.current().pid();

答案 2 :(得分:53)

这是一个后门方法,可能不适用于所有虚拟机,但应该适用于Linux和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);

答案 3 :(得分: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();
    }

答案 4 :(得分:24)

以下方法尝试从java.lang.management.ManagementFactory

中提取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>")

答案 5 :(得分:20)

对于较旧的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";
}

答案 6 :(得分:18)

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

答案 7 :(得分:16)

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

public abstract class Process {

    ...

    public long getPid();
}

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

System.out.println(ProcessHandle.current().pid());

答案 8 :(得分:7)

为了完整性,

Spring Boot 中有一个包装器
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的警告已在其他答案中讨论过。

答案 9 :(得分:7)

在Scala中:

DataFrames

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

答案 10 :(得分: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;
}

答案 11 :(得分:5)

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

答案 12 :(得分:5)

java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]

答案 13 :(得分:4)

这取决于您从哪里寻找信息。

如果要从控制台查找信息,可以使用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,后跟名称。

答案 14 :(得分:2)

基于Ashwin Jayaprakash的answer(+1) 关于Apache 2.0许可SIGAR,以下是我如何使用它来获取当前进程的PID:

import org.hyperic.sigar.Sigar;

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

尽管它并不适用于所有平台,但它确实适用于Linux, Windows, OS X and various Unix platforms as listed here

答案 15 :(得分:2)

这是代码JConsole,可能是jps和VisualVM使用的。它利用来自的类 来自sun.jvmstat.monitor.*的{​​{1}}个包。

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; } } 是一个随Oracle JDK分发但不是JRE的库!
  • 你无法从Maven回购获得tool.jar;使用Maven配置它有点棘手
  • tool.jar可能包含平台相关(本机?)代码,因此不容易  分配
  • 它假设所有(本地)运行的JVM应用程序都是“可监视”的。看起来像  从Java 6开始,所有应用程序通常都是(除非你主动配置相反)
  • 它可能仅适用于Java 6 +
  • Eclipse不发布主类,因此您不会轻易获得Eclipse PID MonitoredVmUtil中的错误?

更新:我刚刚检查过JPS使用这种方式,即Jvmstat库(tool.jar的一部分)。所以没有必要将JPS称为外部进程,直接调用Jvmstat库,如我的示例所示。您可以通过这种方式获取在localhost上运行的所有JVM的列表。 见JPS source code

答案 16 :(得分:1)

我知道这是一个旧线程,但我想要调用用于获取PID的API(以及在运行时对Java进程的其他操作)添加到JDK 9中的Process类:{{3 }}

答案 17 :(得分:1)

您可以在JNR-Posix中尝试getpid()

它有一个Windows POSIX包装器,可以从libc调用getpid()。

答案 18 :(得分:1)

添加到其他解决方案。

使用Java 10

获取process id

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

答案 19 :(得分:1)

我发现了一个可能有点过时的解决方案,我没有在Windows 10以外的其他操作系统上尝试过,但是我认为这是值得注意的。

如果发现自己正在使用J2V8和nodejs,则可以运行一个简单的javascript函数,以返回Java进程的pid。

这里是一个例子:

public static void main(String[] args) {
    NodeJS nodeJS = NodeJS.createNodeJS();
    int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
    System.out.println(pid);
    nodeJS.release();
}

答案 20 :(得分:0)

这是我的解决方案:

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;
    }

答案 21 :(得分:-6)

这是我在有类似要求时使用的。这正确地确定了Java进程的PID。让您的java代码在预定义的端口号上生成服务器,然后执行OS命令以找出在端口上侦听的PID。对于Linux

netstat -tupln | grep portNumber