Java process pid process id

How to get PID of process I’ve just started within java program?

No idea how to do it in Java, but in case it’s your script you may modify it, so it outputs it’s pid and parse it from p.getInputStream().

NOT an «exact duplicate» to the one who voted to close. That question has to do with finding the pid of the Java process itself, not a new process that the Java process spawned.

This returns the PID of the running host VM, the original question was asking what the PID of the child process started from the running Java app would be. This question addresses it: stackoverflow.com/questions/5284139/…

18 Answers 18

Since Java 9 class Process has new method long pid() , so it is as simple as

ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "path"); try < Process p = pb.start(); long pid = p.pid(); >catch (IOException ex) < // . >

There is no public API for this yet. see Sun Bug 4244896, Sun Bug 4250622

returns an Object of type

The Process class is abstract, and what you get back is some subclass of Process which is designed for your operating system. For example on Macs, it returns java.lang.UnixProcess which has a private field called pid . Using Reflection you can easily get the value of this field. This is admittedly a hack, but it might help. What do you need the PID for anyway?

On Windows it returns java.lang.ProcessImpl which has no notion of PID. Your solution is not cross platform unfortunately.

There’s another quite good example which provides reasonable cross-platform support at:github.com/flapdoodle-oss/de.flapdoodle.embed.process/blob/…

I don’t know about the OP but I need to be able to kill and possibly restart the process at some point.

Returns an instance of «java.lang.Win32Process») OR «java.lang.ProcessImpl»

Both have a private field «handle».

This is an OS handle for the process. You will have to use this + Win32 API to query PID. That page has details on how to do that.

In Unix System (Linux & Mac)

 public static synchronized long getPidOfProcess(Process p) < long pid = -1; try < if (p.getClass().getName().equals("java.lang.UNIXProcess")) < Field f = p.getClass().getDeclaredField("pid"); f.setAccessible(true); pid = f.getLong(p); f.setAccessible(false); >> catch (Exception e) < pid = -1; >return pid; > 

@Miha_x64 Field I guess I said that thinking that getDeclaredField() returns always the same instance (it does not). So i can’t hold that statement any more

Include jna (both «JNA» and «JNA Platform») in your library and use this function:

import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinNT; import java.lang.reflect.Field; public static long getProcessID(Process p) < long result = -1; try < //for windows if (p.getClass().getName().equals("java.lang.Win32Process") || p.getClass().getName().equals("java.lang.ProcessImpl")) < Field f = p.getClass().getDeclaredField("handle"); f.setAccessible(true); long handl = f.getLong(p); Kernel32 kernel = Kernel32.INSTANCE; WinNT.HANDLE hand = new WinNT.HANDLE(); hand.setPointer(Pointer.createConstant(handl)); result = kernel.GetProcessId(hand); f.setAccessible(false); >//for unix based operating systems else if (p.getClass().getName().equals("java.lang.UNIXProcess")) < Field f = p.getClass().getDeclaredField("pid"); f.setAccessible(true); result = f.getLong(p); f.setAccessible(false); >> catch(Exception ex) < result = -1; >return result; > 

You can also download JNA from here and JNA Platform from here.

Читайте также:  Блочные элементы

Could you please explain what the above code does? That way any future visitors will understand. Thanks

The answer of Shamit Verma notes why it needs to be done this way. Windows doesn’t give you a PID but a handle, so you need to transform the handle to PID.

Unfortunately the windows side doesn’t work with JDK 9+ anymore, so a little tricky still github.com/jruby/jruby/issues/7515

I think I have found out a solution, that looks quite bulletproof while working on most platforms. Here is the idea:

  1. Create a JVM-wide mutex that you acquire before spawning new process/killing a process
  2. Use platform-dependent code to acquire list of child processes + pids of your JVM process
  3. Spawn new process
  4. Acquire new list of child processes + pids and compare with the previous list. The one that is new is your guy.

Since you check only for child processes, you cannot be wronged by some other process in the same machine. JVM-wide mutex than allows you to be sure, that the new process is the correct one.

Reading child process list is simpler than getting PID from process objects, because it does not require WIN API calls on windows, and, more importantly, it has been done already in several libs.

Below is an implementation of the above idea using JavaSysMon library. It

class UDKSpawner < private int uccPid; private Logger uccLog; /** * Mutex that forces only one child process to be spawned at a time. * */ private static final Object spawnProcessMutex = new Object(); /** * Spawns a new UDK process and sets to it's PID. To work correctly, * the code relies on the fact that no other method in this JVM runs UDK processes and * that no method kills a process unless it acquires lock on spawnProcessMutex. * @param procBuilder * @return */ private Process spawnUDK(ProcessBuilder procBuilder) throws IOException < synchronized (spawnProcessMutex)< JavaSysMon monitor = new JavaSysMon(); DirectUDKChildProcessVisitor beforeVisitor = new DirectUDKChildProcessVisitor(); monitor.visitProcessTree(monitor.currentPid(), beforeVisitor); SetalreadySpawnedProcesses = beforeVisitor.getUdkPids(); Process proc = procBuilder.start(); DirectUDKChildProcessVisitor afterVisitor = new DirectUDKChildProcessVisitor(); monitor.visitProcessTree(monitor.currentPid(), afterVisitor); Set newProcesses = afterVisitor.getUdkPids(); newProcesses.removeAll(alreadySpawnedProcesses); if(newProcesses.isEmpty()) < uccLog.severe("There is no new UKD PID."); >else if(newProcesses.size() > 1) < uccLog.severe("Multiple new candidate UDK PIDs"); >else < uccPid = newProcesses.iterator().next(); >return proc; > > private void killUDKByPID() < if(uccPid < 0)< uccLog.severe("Cannot kill UCC by PID. PID not set."); return; >synchronized(spawnProcessMutex) < JavaSysMon monitor = new JavaSysMon(); monitor.killProcessTree(uccPid, false); >> private static class DirectUDKChildProcessVisitor implements ProcessVisitor < SetudkPids = new HashSet(); @Override public boolean visit(OsProcess op, int i) < if(op.processInfo().getName().equals("UDK.exe"))< udkPids.add(op.processInfo().getPid()); >return false; > public Set getUdkPids() < return udkPids; >> > 

In my testing all IMPL classes had the field «pid». This has worked for me:

public static int getPid(Process process) < try < ClasscProcessImpl = process.getClass(); Field fPid = cProcessImpl.getDeclaredField("pid"); if (!fPid.isAccessible()) < fPid.setAccessible(true); >return fPid.getInt(process); > catch (Exception e) < return -1; >> 

Just make sure the returned value is not -1. If it is, then parse the output of ps .

I used a non-portable approach to retrieve the UNIX PID from the Process object that is very simple to follow.

STEP 1: Use some Reflection API calls to identify the Process implementation class on the target server JRE (remember that Process is an abstract class). If your UNIX implementation is like mine, you will see an implementation class that has a property named pid that contains the PID of the process. Here is the logging code that I used.

 //-------------------------------------------------------------------- // Jim Tough - 2014-11-04 // This temporary Reflection code is used to log the name of the // class that implements the abstract Process class on the target // JRE, all of its 'Fields' (properties and methods) and the value // of each field. // // I only care about how this behaves on our UNIX servers, so I'll // deploy a snapshot release of this code to a QA server, run it once, // then check the logs. // // TODO Remove this logging code before building final release! final Class clazz = process.getClass(); logger.info("Concrete implementation of " + Process.class.getName() + " is: " + clazz.getName()); // Array of all fields in this class, regardless of access level final Field[] allFields = clazz.getDeclaredFields(); for (Field field : allFields) < field.setAccessible(true); // allows access to non-public fields ClassfieldClass = field.getType(); StringBuilder sb = new StringBuilder(field.getName()); sb.append(" | type: "); sb.append(fieldClass.getName()); sb.append(" | value: ["); Object fieldValue = null; try < fieldValue = field.get(process); sb.append(fieldValue); sb.append("]"); >catch (Exception e) < logger.error("Unable to get value for [" + field.getName() + "]", e); >logger.info(sb.toString()); > //-------------------------------------------------------------------- 

STEP 2: Based on the implementation class and field name that you obtained from the Reflection logging, write some code to pickpocket the Process implementation class and retrieve the PID from it using the Reflection API. The code below works for me on my flavour of UNIX. You may have to adjust the EXPECTED_IMPL_CLASS_NAME and EXPECTED_PID_FIELD_NAME constants to make it work for you.

/** * Get the process id (PID) associated with a * @param process , or null * @return Integer containing the PID of the process; null if the * PID could not be retrieved or if a null parameter was supplied */ Integer retrievePID(final Process process) < if (process == null) < return null; >//-------------------------------------------------------------------- // Jim Tough - 2014-11-04 // NON PORTABLE CODE WARNING! // The code in this block works on the company UNIX servers, but may // not work on *any* UNIX server. Definitely will not work on any // Windows Server instances. final String EXPECTED_IMPL_CLASS_NAME = "java.lang.UNIXProcess"; final String EXPECTED_PID_FIELD_NAME = "pid"; final Class processImplClass = process.getClass(); if (processImplClass.getName().equals(EXPECTED_IMPL_CLASS_NAME)) < try < Field f = processImplClass.getDeclaredField( EXPECTED_PID_FIELD_NAME); f.setAccessible(true); // allows access to non-public fields int pid = f.getInt(process); return pid; >catch (Exception e) < logger.warn("Unable to get PID", e); >> else < logger.warn(Process.class.getName() + " implementation was not " + EXPECTED_IMPL_CLASS_NAME + " - cannot retrieve PID" + " | actual type was: " + processImplClass.getName()); >//-------------------------------------------------------------------- return null; // If PID was not retrievable, just return null > 

Источник

Читайте также:  Your email index php

How do I find the process ID (pid) of a process started in java? [duplicate]

If I get a process object in Java through Runtime.getRuntime().exec(. ) , or ProcessBuilder.start() , I can wait for it through Process.waitFor() , which is like Thread.join() , or I could kill it with Process.destroy() , which is like the deprecated Thread.stop() . BUT: How do I find the pid of the Process Object? I don’t see a method for doing that in The Official Documentation. Can I do this in Java? If so, how?

5 Answers 5

This guy calls out to bash to get the PID. I’m not sure if there is an java solution to the problem.

/** * Gets a string representing the pid of this program - Java VM */ public static String getPid() throws IOException,InterruptedException < Vectorcommands=new Vector(); 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 ""; >> 

I think this will give the pid of the JVM process. not the process spawned by Java which I believe is what the question is asking.

I think you need to read a bit closer. It spawns a process thats only job is to echo its own PID to its stdout which itself is piping to the stdin file descriptor associated with the JVM.

Vectors are old-hat, and is synchronized — no real need to use that type of collection — try using an ArrayList instead. Just saying.

Just saying what? This is not germane to the problem. The question is about accessing a PID not java best practices.

Similar to the other tools mentioned, there is the jps command line tool that comes with the Java runtime. It spits out the PIDs of all running JVMs. The benefit is the output one needs to parse is confined to only the JVM processes.

Читайте также:  Javascript new array with length

Leo, after looking into this issue for about a week myself I think Jhurtado’s approach is likely the «best» approach we can manage in Java right now. «best» is in quotes because it has the very nasty side effect of basically being a «guess» at what your child PID is.

If your Java app is spawning native processes quickly in a high-load system, there is NO guarantee that the PID you pickup in your diff calculation is the PID of the Process started by the current Thread or that the PID of the process you pick was even spawned by our app (maybe the host system was already running that process anyway).

That being said, if you are not spawning dozens of processes or the native Process you are spawning is really unique (some custom util you ship with your app) then this approach works fine in which case the PID of the native process you are looking for is the one you want.

On windows you can use ‘tasklist‘ as Jhurtado pointed out to get the full list of PIDs and filter for the one you want (using the /FI filter switch didn’t work for me in testing).

On any *nix system you can use «ps ax | grep » where NAME is some process name like ‘nginx’ or ‘httpd’ that you want to filter for to get your list.

Additionally, if you need to kill stray processes (for example, on VM exit) on *nix you can of course use «kill -9 » and on Windows, interestingly enough, you can use ‘taskkill ‘.

Hardly optimal unfortunately.

Источник

Оцените статью