How do I find my PID in Java or JRuby on Linux?

2019-01-14 07:48发布

问题:

I need to find the PID of the current running process on a Linux platform (it can be a system dependent solution). Java does not support getting the process ID, and JRuby currently has a bug with the Ruby method, Process.pid.

Is there another way to obtain the PID?

回答1:

If you have procfs installed, you can find the process id via the /proc/self symlink, which points to a directory whose name is the pid (there are also files here with other pertinent information, including the PID, but the directory is all you need in this case).

Thus, with Java, you can do:

String pid = new File("/proc/self").getCanonicalFile().getName();

In JRuby, you can use the same solution:

pid = java.io.File.new("/proc/self").canonical_file.name

Special thanks to the #stackoverflow channel on free node for helping me solve this! (specifically, Jerub, gregh, and Topdeck)



回答2:

Only tested in Linux using Sun JVM. Might not work with other JMX implementations.

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


回答3:

You can use the JNI interface to call the POSIX function getpid(). It is quite straight forward. You start with a class for the POSIX functions you need. I call it POSIX.java:

import java.util.*;

class POSIX
{
    static { System.loadLibrary ("POSIX"); }
    native static int getpid ();
}

Compile it with

$ javac POSIX.java

After that you generate a header file POSIX.h with

$ javah -jni POSIX

The header file contains the C prototype for the function with wraps the getpid function. Now you have to implement the function, which is quite easy. I did it in POSIX.c:

#include "POSIX.h"

#include <sys/types.h>
#include <unistd.h>

JNIEXPORT jint JNICALL Java_POSIX_getpid (JNIEnv *env, jclass cls)
{
    return getpid ();
}

Now you can compile it using gcc:

$ gcc -Wall -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include/linux -o libPOSIX.so -shared -Wl,-soname,libPOSIX.so POSIX.c -static -lc

You have to specify the location where your Java is installed. That's all. Now you can use it. Create a simple getpid program:

public class getpid
{
    public static void main (String argv[])
    {
        System.out.println (POSIX.getpid ());
    }
}

Compile it with javac getpid.java and run it:

$ java getpid &
[1] 21983
$ 21983

The first pid is written by the shell and the second is written by the Java program after shell prompt has returned. ∎



回答4:

Spawn a shell process that will read its parent's pid. That must be our pid. Here is the running code, without exception and error handling.

import java.io.*;
import java.util.Scanner;

public class Pid2
{
  public static void main(String sArgs[])
    throws java.io.IOException, InterruptedException
  {
    Process p = Runtime.getRuntime().exec(
      new String[] { "sh", "-c", "ps h -o ppid $$" });
    p.waitFor();
    Scanner sc = new Scanner(p.getInputStream());
    System.out.println("My pid: " + sc.nextInt()); 
    Thread.sleep(5000);
  }
}

This solution seems to be the best if the PID is to be obtained only to issue another shell command. It's enough to wrap the command in back quotes to pass it as an argument to another command, for example:

nice `ps h -o ppid $$`

This may substitue the last string in the array given to exec call.



回答5:

You can try getpid() in JNR-Posix.

It also has a Windows POSIX wrapper that calls getpid() off of libc. No JNI needed.



回答6:

Java 9 finally offers an official way to do so with ProcessHandle:

ProcessHandle.current().pid();

This:

  • First gets a ProcessHandle reference for the current process.

  • In order to access its pid.

No import necessary as ProcessHandle is part of java.lang.