如何获得我的Java进程的id ?

我知道有一些平台相关的黑客,但我更喜欢一个更通用的解决方案。


不存在能够保证在所有jvm实现中工作的与平台无关的方法。 ManagementFactory.getRuntimeMXBean(). getname()看起来是最好的(最接近的)解决方案,通常包括PID。它很简短,并且可能适用于广泛使用的每个实现。

在linux+windows上,它返回一个类似“12345@hostname”的值(12345是进程id)。不过要注意的是,根据文档,这个值并没有保证:

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

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

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

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

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


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


试试西格尔。非常广泛的api。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();
}

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

您可以使用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中,新的进程API可用于获取当前进程ID。首先获取当前进程的句柄,然后查询PID:

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

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


下面的方法尝试从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>")。


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

这是JConsole,可能还有jps和VisualVM使用的代码。它利用类 sun.jvmstat.monitor。* 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;
    }
}

这里有几个问题:

The tool.jar is a library distributed with Oracle JDK but not JRE! You cannot get tool.jar from Maven repo; configure it with Maven is a bit tricky The tool.jar probably contains platform dependent (native?) code so it is not easily distributable It runs under assumption that all (local) running JVM apps are "monitorable". It looks like that from Java 6 all apps generally are (unless you actively configure opposite) It probably works only for Java 6+ Eclipse does not publish main class, so you will not get Eclipse PID easily Bug in MonitoredVmUtil?

更新:我刚刚再次检查了JPS使用这种方式,即Jvmstat库(tool.jar的一部分)。因此,不需要调用JPS作为外部进程,直接调用Jvmstat库,如我的示例所示。你也可以通过这种方式获取在本地主机上运行的所有jvm的列表。 参见JPS源代码:


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

netstat -tupln | grep portNumber

基于Ashwin Jayaprakash的答案(+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和这里列出的各种Unix平台上工作。


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

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


我知道这是一个旧线程,但我想要调用用于获取PID的API(以及在运行时对Java进程的其他操作)正在添加到JDK 9中的process类:http://openjdk.java.net/jeps/102


自Java 9以来,有一个方法process . getpid(),它返回进程的本机ID:

public abstract class Process {

    ...

    public long getPid();
}

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

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

以下是我的解决方案:

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

在Scala中:

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

在Java 9发布之前,这将为您在Unix系统上提供一个变通方案。 (我知道,这个问题是关于Java的,但由于Scala没有相应的问题,所以我想把这个问题留给Scala用户,他们可能会遇到同样的问题。)


为完整起见,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的注意事项已经在其他回答中讨论过了。


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]

我把这个加上其他解。

使用Java 10,获取进程id

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

我发现了一个可能有点极端的解决方案,除了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();
}