Java 程序如何获得自己的进程 ID?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can a Java program get its own process ID?
提问by Dmitry Shechtman
How do I get the id of my Java process?
如何获取我的 Java 进程的 ID?
I know there are several platform-dependent hacks, but I would prefer a more generic solution.
我知道有几个依赖于平台的黑客,但我更喜欢更通用的解决方案。
采纳答案by Wouter Coekaerts
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. It's short, and probablyworks in every implementation in wide use.
不存在可以保证在所有 jvm 实现中工作的独立于平台的方式。
ManagementFactory.getRuntimeMXBean().getName()
看起来是最好的(最接近的)解决方案。它很短,可能适用于广泛使用的每个实现。
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:
在 linux+windows 上,它返回一个类似的值12345@hostname
(12345
即进程 ID)。请注意,根据 docs,无法保证此值:
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.
返回代表正在运行的 Java 虚拟机的名称。返回的名称字符串可以是任意字符串,Java 虚拟机实现可以选择在返回的名称字符串中嵌入特定于平台的有用信息。每个正在运行的虚拟机可以有不同的名称。
In Java 9the new process APIcan be used:
在 Java 9 中,可以使用新的进程 API:
long pid = ProcessHandle.current().pid();
回答by Ryan P
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
如果要从控制台查找信息,可以使用 jps 命令。该命令提供类似于 Unix ps 命令的输出,并且随 JDK 一起提供,因为我相信 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:
如果您从流程来看,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);
If run with no options the output should be the process id followed by the name.
如果不带任何选项运行,则输出应该是进程 ID 后跟名称。
回答by Jez Humble
You can check out my project: JavaSysMonon GitHub. It provides process id and a bunch of other stuff (CPU usage, memory usage) cross-platform (presently Windows, Mac OSX, Linux and Solaris)
您可以查看我的项目:GitHub 上的JavaSysMon。它提供进程 ID 和一堆其他东西(CPU 使用率、内存使用率)跨平台(目前是 Windows、Mac OSX、Linux 和 Solaris)
回答by Ashwin Jayaprakash
Try Sigar. very extensive APIs. Apache 2 license.
试试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();
}
回答by Ashwin Jayaprakash
For older JVM, in linux...
对于较旧的 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";
}
回答by Luke Quinane
You could use JNA. Unfortunately there is no common JNA API to get the current process ID yet, but each platform is pretty simple:
你可以使用JNA。不幸的是,目前还没有通用的 JNA API 来获取当前进程 ID,但每个平台都非常简单:
Windows
视窗
Make sure you have jna-platform.jar
then:
确保你有jna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
Unix
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
爪哇 9
Under Java 9 the new process APIcan be used to get the current process ID. First you grab a handle to the current process, then query the PID:
在 Java 9 下,新的进程 API可用于获取当前进程 ID。首先获取当前进程的句柄,然后查询 PID:
long pid = ProcessHandle.current().pid();
回答by Jared
The latest I have found is that there is a system propertycalled 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
.
我发现的最新消息是至少在 linux 上有一个名为的系统属性sun.java.launcher.pid
。我的计划是使用它,如果没有发现使用JMX bean
.
回答by Martin
The following method tries to extract the PID from java.lang.management.ManagementFactory
:
以下方法尝试从 中提取 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;
}
Just call getProcessId("<PID>")
, for instance.
getProcessId("<PID>")
例如,只需调用。
回答by Brad Mace
Here's a backdoor method which mightnot work with all VMs but should work on both linux and windows (original example here):
这是一个后门方法,它可能不适用于所有 VM,但应该适用于 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);
回答by Espinosa
This is the code JConsole, and potentially jps and VisualVM uses. It utilizes classes from
sun.jvmstat.monitor.*
package, from tool.jar
.
这是 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;
}
}
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?
- 这
tool.jar
是一个随 Oracle JDK 而不是 JRE 分发的库! - 您无法
tool.jar
从 Maven 仓库获取;用 Maven 配置它有点棘手 - 将
tool.jar
可能包含与平台相关的(原生?)代码,因此它不容易分派 - 它在假设所有(本地)运行的 JVM 应用程序都是“可监控的”的情况下运行。看起来从 Java 6 开始,所有应用程序通常都是(除非您主动配置相反)
- 它可能只适用于 Java 6+
- Eclipse 不发布主类,所以你不会轻易得到Eclipse PID MonitoredVmUtil 中的Bug?
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:
更新:我刚刚仔细检查了 JPS 使用这种方式,即 Jvmstat 库(tool.jar 的一部分)。所以不需要调用JPS作为外部进程,直接调用Jvmstat库,如我的例子所示。您还可以通过这种方式获取在本地主机上运行的所有 JVM 的列表。查看 JPS源代码: