raf*_*raf 66 java pid process processbuilder
我已经开始使用以下代码进行处理
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "path");
try {
Process p = pb.start();
}
catch (IOException ex) {}
Run Code Online (Sandbox Code Playgroud)
现在我需要知道我刚刚开始的进程的pid.
Ami*_*ani 25
目前还没有公共API.见Sun Bug 4244896,Sun Bug 4250622
作为解决方法:
Runtime.exec(...)
Run Code Online (Sandbox Code Playgroud)
返回一个类型的Object
java.lang.Process
Run Code Online (Sandbox Code Playgroud)
Process类是抽象的,你得到的是Process的一些子类,它是为你的操作系统设计的.例如,在Mac上,它返回java.lang.UnixProcess有一个名为的私有字段pid.使用Reflection,您可以轻松获得此字段的值.这无疑是一个黑客,但它可能会有所帮助.PID无论如何你还需要什么?
Sha*_*rma 24
这个页面有HOWTO:
http://www.golesny.de/p/code/javagetpid
在Windows上:
Runtime.exec(..)
Run Code Online (Sandbox Code Playgroud)
返回"java.lang.Win32Process")或"java.lang.ProcessImpl"的实例
两者都有一个私人领域"句柄".
这是该过程的OS句柄.您将不得不使用此+ Win32 API来查询PID.该页面详细介绍了如何执行此操作.
cze*_*rny 24
由于Java 9类Process有新方法long pid(),所以就这么简单
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "path");
try {
Process p = pb.start();
long pid = p.pid();
} catch (IOException ex) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
LRB*_*H10 19
在Unix系统(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;
}
Run Code Online (Sandbox Code Playgroud)
arc*_*sin 14
在库中包含jna("JNA"和"JNA平台")并使用此功能:
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;
}
Run Code Online (Sandbox Code Playgroud)
我想我找到了一个解决方案,在大多数平台上工作时看起来非常防弹.这是一个想法:
由于您只检查子进程,因此不能被同一台计算机中的某些其他进程所冤枉.JVM范围的互斥锁比允许您确定新进程是正确的.
读取子进程列表比从进程对象获取PID更简单,因为它不需要在Windows上进行WIN API调用,更重要的是,它已经在几个库中完成了.
下面是使用JavaSysMon库实现上述想法.它
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 {@link #uccPid} 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);
Set<Integer> alreadySpawnedProcesses = beforeVisitor.getUdkPids();
Process proc = procBuilder.start();
DirectUDKChildProcessVisitor afterVisitor = new DirectUDKChildProcessVisitor();
monitor.visitProcessTree(monitor.currentPid(), afterVisitor);
Set<Integer> 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 {
Set<Integer> udkPids = new HashSet<Integer>();
@Override
public boolean visit(OsProcess op, int i) {
if(op.processInfo().getName().equals("UDK.exe")){
udkPids.add(op.processInfo().getPid());
}
return false;
}
public Set<Integer> getUdkPids() {
return udkPids;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的测试中,所有 IMPL 类都有“pid”字段。这对我有用:
public static int getPid(Process process) {
try {
Class<?> cProcessImpl = process.getClass();
Field fPid = cProcessImpl.getDeclaredField("pid");
if (!fPid.isAccessible()) {
fPid.setAccessible(true);
}
return fPid.getInt(process);
} catch (Exception e) {
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
只要确保返回值不为-1即可。如果是,则解析 的输出ps。