web-dev-qa-db-ja.com

Javaで開始されたプロセスのプロセスID(pid)を見つけるにはどうすればよいですか?

Javaを介してRuntime.getRuntime().exec(...)、またはProcessBuilder.start()でプロセスオブジェクトを取得した場合、Process.waitFor()を介して待機できます。 Thread.join()のようなもの、またはProcess.destroy()を使用して強制終了することもできます。これは非推奨のThread.stop()のようなものです。

しかし、どのようにプロセスオブジェクトのpidを見つけるのですか? The Official Documentation にそれを行う方法がありません。 Javaでこれを行うことはできますか?もしそうなら、どのように?

21
Leo Izen

この男は、PIDを取得するためにbashを呼び出します。 Java問題の解決策があるかどうかはわかりません。

/**
 * Gets a string representing the pid of this program - Java VM
 */
public static String getPid() throws IOException,InterruptedException {

  Vector<String> commands=new Vector<String>();
  commands.add("/bin/bash");
  commands.add("-c");
  commands.add("echo $PPID");
  ProcessBuilder pb=new ProcessBuilder(commands);

  Process pr=pb.start();
  pr.waitFor();
  if (pr.exitValue()==0) {
    BufferedReader outReader=new BufferedReader(new InputStreamReader(pr.getInputStream()));
    return outReader.readLine().trim();
  } else {
    System.out.println("Error while getting PID");
    return "";
  }
}

ソース: http://www.coderanch.com/t/109334/Linux-UNIX/UNIX-process-ID-Java-program

10
nsfyn55

前述の他のツールと同様に、Javaランタイム。付属のjpsコマンドラインツールがあります。実行中のすべてのJVMのPIDを出力します。利点は出力です解析する必要があるのは、JVMプロセスのみに限定されます。

7
Brent Worden

レオ、私自身でこの問題を1週間ほど調べた後、私はJhurtadoのアプローチがおそらくJavaで管理できる「最良の」アプローチだと思います。基本的にあなたの子供のPIDが何であるかを「推測する」という非常に厄介な副作用。

Javaアプリが高負荷システムでネイティブプロセスをすばやく生成している場合、差分計算で取得したPIDが現在のスレッドによって開始されたプロセスのPIDであるという保証はありません。選択したプロセスのPIDがアプリによって生成されたことさえあります(ホストシステムがそのプロセスを既に実行していた可能性があります)。

つまり、数十のプロセスを生成していない場合、または生成しているネイティブプロセスが本当にユニークな場合(アプリに付属するカスタムutil)、このアプローチはうまく機能します。その場合、探しているネイティブプロセスのPIDあなたが望むものです。

Jhurtadoが指摘したように、Windowsでは「tasklist」を使用してPIDの完全なリストを取得し、必要なものをフィルタリングできます(テストでは/ FIフィルタースイッチを使用しても機能しませんでした)。

任意の* nixシステムで、「ps ax | grep」を使用できます。NAMEは、リストを取得するためにフィルタリングする「nginx」や「httpd」などのプロセス名です。

さらに、* nixで迷ったプロセスを強制終了する必要がある場合(たとえば、on VM exit))、「kill -9」およびWindowsでは、興味深いことに、「taskkill」を使用できます。

残念ながらほとんど最適ではありません。

0
Riyad Kalla

私はあなたと同じ問題に遭遇しました。私はかなりまともな解決策を見つけました。プロセスが公式に開始されたことを確認する前に、わずかな睡眠をお勧めします。

Process p = Runtime.getRuntime().exec("cmd /c tasklist");
StringWriter writer = new StringWriter();
IOUtils.copy(p.getInputStream(), writer);
String theString = writer.toString();
//System.out.println(theString);
id = findLastString("javaw.exe                     .{1,} Console                    1", theString);
System.out.println(id);

findLastStringは次のように定義されます

public static String findLastString(String pattern, String in) {
     Pattern p = Pattern.compile(pattern);
     Matcher matcher = p.matcher(in);
     String it= "";
     while(matcher.find()) {
       it = matcher.group();
       try {
        Thread.sleep(10);
       } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
       }
     }
     int firstIndex=pattern.indexOf(".{1,}");
     int lastIndex=it.substring(firstIndex).indexOf(pattern.substring(pattern.indexOf(".{1,}")+5))+firstIndex;
     String dotOn = it.substring(pattern.indexOf(".{1,}"));

     it=it.substring(firstIndex, lastIndex);
     return it;
 }

基本的に、これは実行中のプロセスのリストを取得し、このインスタンスではjavaw.exeという名前で最後に実行されたプロセスを見つけます(私のプログラムは別のJavaプロセス)を開始しました。 javaw.exeを、タスクマネージャーを使用して見つけることができるプロセスの名前に置き換えます。Apachecommon IO jarも取得する必要があります。

0
Alex Coleman