JavaプロセスのIDを取得するにはどうすればよいですか?
プラットフォームに依存したハックがいくつかあることは知っていますが、より一般的な解決策を望みます。
JavaプロセスのIDを取得するにはどうすればよいですか?
プラットフォームに依存したハックがいくつかあることは知っていますが、より一般的な解決策を望みます。
回答:
すべてのjvm実装での動作を保証できる、プラットフォームに依存しない方法はありません。
ManagementFactory.getRuntimeMXBean().getName()
最高の(最も近い)ソリューションのように見えます。これは短く、おそらく広く使用されているすべての実装で機能します。
Linux + Windowsでは、12345@hostname
(12345
プロセスIDである)のような値を返します。docsによると、この値については保証されないことに注意してください:
実行中のJava仮想マシンを表す名前を返します。返される名前文字列は任意の文字列にすることができ、Java仮想マシンの実装では、返される名前文字列にプラットフォーム固有の有用な情報を埋め込むことを選択できます。実行中の仮想マシンごとに異なる名前を付けることができます。
Java 9では、新しいプロセスAPIを使用できます。
long pid = ProcessHandle.current().pid();
JNAを使用できます。残念ながら、現在のプロセスIDを取得する共通のJNA APIはまだありませんが、各プラットフォームは非常に単純です。
あなたがしていることを確認してくださいjna-platform.jar
:
int pid = Kernel32.INSTANCE.GetCurrentProcessId();
宣言:
private interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
int getpid ();
}
次に:
int pid = CLibrary.INSTANCE.getpid();
Java 9では、新しいプロセスAPIを使用して現在のプロセスIDを取得できます。最初に現在のプロセスのハンドルを取得し、次にPIDをクエリします。
long pid = ProcessHandle.current().pid();
getpid()
ソリューションはOS Xでも機能し、JNAが「システム」ライブラリを呼び出します。
error: cannot find symbol
はjdk9 に乗ります
これは、すべての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);
getDeclaredMethod
によって返されたオブジェクトに対してを実行するだけjvm.get(runtime)
です。
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();
}
次のメソッドは、から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;
}
getProcessId("<PID>")
たとえばを呼び出すだけです。
古い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";
}
int pid = Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
。なぜ余分な旋回が必要なのですか?
getCanonicalFile()
「自己」をPIDに変換するメソッドにある種の魔法?
私のプロジェクト、GitHubのJavaSysMonをチェックしてください。プロセスIDとその他の要素(CPU使用量、メモリ使用量)のクロスプラットフォーム(現在はWindows、Mac OSX、Linux、Solaris)を提供します
Java 9以降、プロセスのネイティブIDを返すProcess.getPid()メソッドがあります。
public abstract class Process {
...
public long getPid();
}
現在のJavaプロセスのプロセスIDを取得するには、ProcessHandle
インターフェースを使用できます。
System.out.println(ProcessHandle.current().pid());
完全を期すため、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を使用する警告は、他の回答ですでに説明されています。
私が見つけた最新のものは、少なくともLinuxで利用できるというシステムプロパティがあるsun.java.launcher.pid
ことです。私の計画はそれを使用することであり、それを使用することが見つからない場合JMX bean
。
それはどこから情報を探しているかによります。
コンソールから情報を探している場合は、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の後に名前が続くはずです。
これは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と一緒に配布するライブラリです!tool.jar
Mavenリポジトリから取得することはできません。Mavenでそれを構成することは少しトリッキーですtool.jar
それは簡単に配布可能ではありませんので、おそらくプラットフォーム依存(ネイティブ?)コードが含まれています更新:JPSがこのように使用すること、つまりJvmstatライブラリ(tool.jarの一部)を再確認しました。したがって、JPSを外部プロセスとして呼び出す必要はありません。私の例が示すように、Jvmstatライブラリを直接呼び出します。この方法で、localhostで実行されているすべてのJVMのリストを取得することもできます。JPS ソースコードを参照してください:
Apache 2.0ライセンスについてのAshwin Jayaprakashの回答(+1)に基づいてSIGAR
、現在のプロセスのPIDのみを取得する方法を以下に示します。
import org.hyperic.sigar.Sigar;
Sigar sigar = new Sigar();
long pid = sigar.getPid();
sigar.close();
すべてのプラットフォームで動作するわけではありませんが、ここに記載されているLinux、Windows、OS X、およびさまざまなUnixプラットフォームで動作します。
あなたは試すことができますgetpid()
にJNR-のPosix。
libcからgetpid()を呼び出すWindows POSIXラッパーがあります。
私はこれが古いスレッドであることを知っていますが、PDKを取得するためのAPI(および実行時のJavaプロセスの他の操作)をJDK 9のProcessクラスに追加したいと考えていました:http:// openjdk。 java.net/jeps/102
ちょっとした問題かもしれない解決策を見つけ、Windows 10以外のOSで試してみませんでしたが、注目に値すると思います。
あなた自身が作業して見つけた場合J2V8とnodejs、あなたはあなたのJavaプロセスのPIDを返す簡単なJavaScript関数を実行することができます。
次に例を示します。
public static void main(String[] args) {
NodeJS nodeJS = NodeJS.createNodeJS();
int pid = nodeJS.getRuntime().executeIntegerScript("process.pid;\n");
System.out.println(pid);
nodeJS.release();
}
これが私の解決策です:
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;
}