387

JavaプロセスのIDを取得するにはどうすればよいですか?

プラットフォームに依存するハックがいくつかあることは知っていますが、より一般的なソリューションをお勧めします。

4

22 に答える 22

383

すべての jvm 実装で動作することを保証できる、プラットフォームに依存しない方法はありません。 ManagementFactory.getRuntimeMXBean().getName()最適な (最も近い) ソリューションのように見え、通常は PID が含まれています。それは短く、おそらく広く使用されているすべての実装で機能します。

Linux+Windows では、"12345@hostname"(12345プロセス ID) のような値を返します。docs によると、この値についての保証はないことに注意してください。

実行中の Java 仮想マシンを表す名前を返します。返される名前文字列は任意の文字列にすることができ、Java 仮想マシンの実装では、返された名前文字列にプラットフォーム固有の有用な情報を埋め込むことができます。実行中の各仮想マシンは、異なる名前を持つことができます。

Java 9では、新しいプロセス APIを使用できます。

long pid = ProcessHandle.current().pid();
于 2008-08-30T11:11:17.277 に答える
125

JNAを使用できます。残念ながら、現在のプロセス ID を取得するための一般的な JNA API はまだありませんが、各プラットフォームは非常に単純です。

ウィンドウズ

次のことを確認してください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();
于 2011-09-05T02:33:57.293 に答える
63

すべての 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);
于 2012-08-22T05:19:41.507 に答える
36

シガーを試してみてください。非常に広範な 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();
}
于 2010-06-28T18:09:17.320 に答える
28

次のメソッドは、から 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>")たとえば、 を呼び出すだけです。

于 2011-10-07T16:32:52.800 に答える
25

古い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";
}
于 2011-06-16T12:56:19.173 に答える
19

Java 9 以降、プロセスのネイティブ ID を返す Process.getPid() メソッドがあります。

public abstract class Process {

    ...

    public long getPid();
}

現在の Java プロセスのプロセス ID を取得するには、次のProcessHandleインターフェイスを使用できます。

System.out.println(ProcessHandle.current().pid());
于 2015-06-26T11:56:20.053 に答える
18

私のプロジェクトをチェックアウトできます: GitHub のJavaSysMon。プロセス ID とその他のもの (CPU 使用率、メモリ使用率) クロスプラットフォーム (現在は Windows、Mac OSX、Linux、Solaris) を提供します。

于 2009-12-26T00:44:59.740 に答える
10

スカラの場合:

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

これにより、Java 9 がリリースされるまでの Unix システムでの回避策が得られるはずです。(質問はJavaに関するものでしたが、Scalaには同等の質問がないため、同じ質問に出くわす可能性のあるScalaユーザーのためにこれを残したいと思いました。)

于 2015-11-20T23:32:12.827 に答える
10
java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]
于 2017-04-13T19:09:59.480 に答える
7
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;
}
于 2016-09-28T10:14:19.307 に答える
5

私が見つけた最新の情報は、少なくとも Linux で利用できるというシステム プロパティがあることです。sun.java.launcher.pid私の計画はそれを使用することであり、それが見つからない場合はJMX bean.

于 2011-09-05T13:47:41.443 に答える
4

どこから情報を探しているかによって異なります。

コンソールから情報を探している場合は、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 の後に名前が続きます。

于 2008-09-04T01:07:49.930 に答える
4

これは 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.jarMaven リポジトリから取得することはできません。Mavenで構成するのは少し難しい
  • tool.jarおそらくプラットフォームに依存する (ネイティブ?) コードが含まれているため、簡単に配布することはできません。
  • これは、(ローカルで) 実行中のすべての JVM アプリが「監視可能」であるという前提で実行されます。Java 6以降、すべてのアプリは一般的にそうであるように見えます(反対に積極的に構成しない限り)
  • おそらくJava 6+でのみ機能します
  • Eclipse はメイン クラスを公開していないため、Eclipse の PID を簡単に取得できません MonitoredVmUtil にバグがありますか?

更新:JPSがこのように使用していること、つまりJvmstatライブラリ(tool.jarの一部)であることを再確認しました。したがって、JPS を外部プロセスとして呼び出す必要はありません。私の例が示すように、Jvmstat ライブラリを直接呼び出します。この方法で、localhost で実行されているすべての JVM のリストを取得することもできます。JPSソース コードを参照してください。

于 2013-06-27T16:28:17.887 に答える
2

Apache 2.0 ライセンスに関する Ashwin Jayaprakash の回答SIGAR(+1) に基づいて、現在のプロセスの PID のみを取得するためにそれを使用する方法を次に示します。

import org.hyperic.sigar.Sigar;

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

すべてのプラットフォームで動作するわけではありませんが、ここにリストされているように、Linux、Windows、OS X、およびさまざまな Unix プラットフォームで動作します

于 2014-02-11T12:47:46.457 に答える
-6

これは、同様の要件があったときに使用したものです。これにより、Java プロセスの PID が正しく決定されます。Java コードで事前に定義されたポート番号でサーバーを生成し、OS コマンドを実行して、ポートでリッスンしている PID を見つけます。Linux の場合

netstat -tupln | grep portNumber
于 2013-09-30T09:42:13.883 に答える