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

发布于 2024-07-04 18:03:36 字数 66 浏览 6 评论 0 原文

如何获取我的 Java 进程的 ID?

我知道有几种依赖于平台的技巧,但我更喜欢更通用的解决方案。

How do I get the id of my Java process?

I know there are several platform-dependent hacks, but I would prefer a more generic solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

半衾梦 2024-07-11 18:03:37

基于 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 平台如此处所列

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();

Even though it does not work on all platforms, it does work on Linux, Windows, OS X and various Unix platforms as listed here.

懒的傷心 2024-07-11 18:03:37

这是我的解决方案:

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

Here is my solution:

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;
    }
感性不性感 2024-07-11 18:03:37

对于JDK< Linux 上的 9:

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.NoSuchFileException;

public static int getPid() {
    try {
        return Integer.parseInt(Files.readSymbolicLink(Paths.get("/proc/self")).toString());
    } catch (NoSuchFileException e) {
        return -1;
    } catch (NumberFormatException e) {
        return -1;
    } catch (IOException e) {
        return -1;
    }
}

您不需要解析文本格式的 /proc/self/stat,只需使用 syscall:readlinkprocfs 实现。

For JDK < 9 on Linux:

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.NoSuchFileException;

public static int getPid() {
    try {
        return Integer.parseInt(Files.readSymbolicLink(Paths.get("/proc/self")).toString());
    } catch (NoSuchFileException e) {
        return -1;
    } catch (NumberFormatException e) {
        return -1;
    } catch (IOException e) {
        return -1;
    }
}

You don't need to parse the text-formatted /proc/self/stat, just use the syscall:readlink and the procfs implementation.

蘸点软妹酱 2024-07-11 18:03:37

我发现了一个可能有点边缘情况的解决方案,并且我没有在 Windows 10 之外的其他操作系统上尝试过它,但我认为它值得注意。

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

这是一个例子:

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

I found a solution that may be a bit of an edge case and I didn't try it on other OS than Windows 10, but I think it's worth noticing.

If you find yourself working with J2V8 and nodejs, you can run a simple javascript function returning you the pid of the java process.

Here is an example:

public static void main(String[] args) {
    NodeJS nodeJS = NodeJS.createNodeJS();
    int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
    System.out.println(pid);
    nodeJS.release();
}
岁月如刀 2024-07-11 18:03:37

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

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

You can try getpid() in JNR-Posix.

It has a Windows POSIX wrapper that calls getpid() off of libc.

自由如风 2024-07-11 18:03:37

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

I know this is an old thread, but I wanted to call out that API for getting the PID (as well as other manipulation of the Java process at runtime) is being added to the Process class in JDK 9: http://openjdk.java.net/jeps/102

苍白女子 2024-07-11 18:03:37

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

有几个问题:

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

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

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

There are few catches:

  • 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?

UPDATE: 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:

鲜肉鲜肉永远不皱 2024-07-11 18:03:37

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

netstat -tupln | grep portNumber

This is what I used when I had similar requirement. This determines the PID of the Java process correctly. Let your java code spawn a server on a pre-defined port number and then execute OS commands to find out the PID listening on the port. For Linux

netstat -tupln | grep portNumber
青丝拂面 2024-07-11 18:03:36

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

Windows

确保您有 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();

You could use JNA. Unfortunately there is no common JNA API to get the current process ID yet, but each platform is pretty simple:

Windows

Make sure you have jna-platform.jar then:

int pid = Kernel32.INSTANCE.GetCurrentProcessId();

Unix

Declare:

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

Then:

int pid = CLibrary.INSTANCE.getpid();

Java 9

Under Java 9 the new process API can be used to get the current process ID. First you grab a handle to the current process, then query the PID:

long pid = ProcessHandle.current().pid();
蓬勃野心 2024-07-11 18:03:36

在 Scala 中:

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

这应该为您提供 Unix 系统上的解决方法,直到 Java 9 发布。
(我知道,这个问题是关于 Java 的,但由于 Scala 没有类似的问题,所以我想把这个问题留给可能遇到同样问题的 Scala 用户。)

In 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.)

澜川若宁 2024-07-11 18:03:36
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
九命猫 2024-07-11 18:03:36

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

Here's a backdoor method which might not work with all VMs but should work on both linux and 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);
森末i 2024-07-11 18:03:36

不存在可以保证在所有 jvm 实现中工作的独立于平台的方法。
ManagementFactory.getRuntimeMXBean().getName() 看起来是最好(最接近)的解决方案,通常包含 PID。 它很短,可能适用于广泛使用的每个实现。

在 linux+windows 上,它返回一个类似 "12345@hostname" 的值(12345 是进程 ID)。 但请注意 根据文档,对此值没有任何保证:

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

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

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

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.

On linux+windows it returns a value like "12345@hostname" (12345 being the process id). Beware though that according to the docs, there are no guarantees about this value:

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.

In Java 9 the new process API can be used:

long pid = ProcessHandle.current().pid();
笑红尘 2024-07-11 18:03:36

使用 Java 10,获取进程 ID

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

With Java 10, to get process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + pid);
安穩 2024-07-11 18:03:36
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;
}
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;
}
娇纵 2024-07-11 18:03:36

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

如果您要从控制台查找信息,可以使用 jps 命令。 该命令提供类似于 Unix ps 命令的输出,并且自 1.5 起就随 JDK 一起提供。

如果您从进程中查看,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 后跟名称。

It depends on where you are looking for the information from.

If you are looking for the information from the console you can use the jps command. The command gives output similar to the Unix ps command and comes with the JDK since I believe 1.5

If you are looking from the process the RuntimeMXBean (as said by Wouter Coekaerts) is probably your best choice. The output from getName() on Windows using Sun JDK 1.6 u7 is in the form [PROCESS_ID]@[MACHINE_NAME]. You could however try to execute jps and parse the result from that:

String jps = [JDK HOME] + "\\bin\\jps.exe";
Process p = Runtime.getRuntime().exec(jps);

If run with no options the output should be the process id followed by the name.

飘过的浮云 2024-07-11 18:03:36

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

The latest I have found is that there is a system property called sun.java.launcher.pid that is available at least on linux. My plan is to use that and if it is not found to use the JMX bean.

近箐 2024-07-11 18:03:36

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

For completeness there is a wrapper in Spring Boot for the

String jvmName = ManagementFactory.getRuntimeMXBean().getName();
return jvmName.split("@")[0];

solution. If an integer is required, then this can be summed up to the one-liner:

int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);

If someone uses Spring boot already, she/he might use org.springframework.boot.ApplicationPid

ApplicationPid pid = new ApplicationPid();
pid.toString();

The toString() method prints the pid or '???'.

Caveats using the ManagementFactory are discussed in other answers already.

貪欢 2024-07-11 18:03:36

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

For older JVM, in 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";
}
枕头说它不想醒 2024-07-11 18:03:36

您可以在 GitHub 上查看我的项目:JavaSysMon。 它提供进程 ID 和一堆其他跨平台信息(CPU 使用情况、内存使用情况)(目前为 Windows、Mac OSX、Linux 和 Solaris)

You can check out my project: JavaSysMon on GitHub. It provides process id and a bunch of other stuff (CPU usage, memory usage) cross-platform (presently Windows, Mac OSX, Linux and Solaris)

夏天碎花小短裙 2024-07-11 18:03:36

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

public abstract class Process {

    ...

    public long pid();
}

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

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

Since Java 9 there is a method Process.pid() which returns the native ID of a process:

public abstract class Process {

    ...

    public long pid();
}

To get the process ID of the current Java process one can use the ProcessHandle interface:

System.out.println(ProcessHandle.current().pid());
不气馁 2024-07-11 18:03:36

尝试 Sigar 。 非常广泛的 API。 阿帕奇 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();
}

Try Sigar . very extensive APIs. 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();
}
梦在夏天 2024-07-11 18:03:36

以下方法尝试从 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("") 即可。

The following method tries to extract the PID from 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;
}

Just call getProcessId("<PID>"), for instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文