java - tutorial - jruby vs ruby




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

Here's a backdoor method which might not work with all VMs but should work on both linux and windows (original example here):

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);

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?


I don't believe this is something Java supplies. For a start, it breaks the platform-independent nature. I can see two ways to approach it, both assuming you're running under a UNIX-type system.

  • provide a JNI which will call getpid() and return it.
  • use system or one of the Runtime methods to run an external program which will call getppid() to get the PID of its parent (i.e., Java), or worse case, walk up the process tree until you find Java itself.

I'm trying to solve the same problem, and since my program must run on OS X, the Linux-only solution didn't work for me.

I came to the same conclusion as the other people on this page -- there isn't a POSIX-compatible way of notifying a child when a parent dies. So I kludged up the next-best thing -- having the child poll.

When a parent process dies (for any reason) the child's parent process becomes process 1. If the child simply polls periodically, it can check if its parent is 1. If it is, the child should exit.

This isn't great, but it works, and it's easier than the TCP socket/lockfile polling solutions suggested elsewhere on this page.


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 # channel on free node for helping me solve this! (specifically, Jerub, gregh, and Topdeck)


You can do this using JMX, but beware. The below is not an officially supported mechanism and could change. However, I've used this in the past and it works fine.

RuntimeMXBean rmxb = ManagementFactory.getRuntimeMXBean();
System.err.println("pid: " + rmxb.getName());

will print {pid}@hostname


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. ∎


How can a Java program get its own process ID?

There exists no platform-independent way that can be guaranteed to work in all jvm implementations. ManagementFactory.getRuntimeMXBean().getName() looks like the best (closest) solution. It's short, and probably works in every implementation in wide use.

On linux+windows it returns a value like [email protected] (12345 being the process id). Beware though that according to the docs, there are no guarantees about this value:

Returns the name representing the running Java virtual machine. The returned name string can be any arbitrary string and a Java virtual machine implementation can choose to embed platform-specific useful information in the returned name string. Each running virtual machine could have a different name.

In Java 9 the new process API can be used:

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

How to make child process die after parent exits?

Child can ask kernel to deliver SIGHUP (or other signal) when parent dies by specifying option PR_SET_PDEATHSIG in prctl() syscall like this:

prctl(PR_SET_PDEATHSIG, SIGHUP);

See man 2 prctl for details.

Edit: This is Linux-only







pid