Java プログラムはどのようにして独自のプロセス ID を取得できるのでしょうか?

StackOverflow https://stackoverflow.com/questions/35842

  •  09-06-2019
  •  | 
  •  

質問

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

プラットフォームに依存するハッキングがいくつかあることは承知していますが、私はより一般的な解決策を希望します。

役に立ちましたか?

解決

すべての JVM 実装で動作することを保証できる、プラットフォームに依存しない方法は存在しません。ManagementFactory.getRuntimeMXBean().getName() 最良の(最も近い)解決策のように見えます。短いし、 おそらく 広く使用されているあらゆる実装で機能します。

Linux+Windowsでは次のような値を返します。 12345@hostname (12345 はプロセス ID です)。ただし注意してください ドキュメントによると, 、この値については保証がありません。

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

Java9では 新しい プロセス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();

Java9

Java 9 では、新しい プロセスAPI 現在のプロセス ID を取得するために使用できます。まず現在のプロセスへのハンドルを取得し、次に PID をクエリします。

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

バックドアメソッドは次のとおりです かもしれない すべての 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);

試す シガール 。非常に広範な API。Apache2ライセンス。

    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>"), 、 例えば。

Linux の古い JVM の場合...

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

私のプロジェクトをチェックアウトしてください: JavaSysMon GitHub 上で。プロセス 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());

スカラの場合:

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

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

完全を期すためにラッパーがあります スプリングブーツ のために

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

解決。整数が必要な場合は、次の 1 行にまとめることができます。

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

誰かがすでに Spring Boot を使用している場合は、次のように使用する可能性があります。 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;
}

私が最近発見したのは、 システムプロパティ 呼ばれた sun.java.launcher.pid それは少なくとも Linux では利用可能です。私の計画では、それを使用し、それが見つからない場合は、 JMX bean.

java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]

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

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

アシュウィン・ジャヤプラカシュの作品に基づく 答え (+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 プラットフォーム.

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

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

あなたが試すことができます getpid()国鉄-ポシックス.

libc から getpid() を呼び出す Windows POSIX ラッパーがあります。

これが古いスレッドであることは承知していますが、PID を取得するための 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();
}

他のソリューションに追加する。

Java 10 で取得するには process id

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
out.println("Process ID is '" + 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;
    }

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

netstat -tupln | grep portNumber
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top