Fields Summary |
---|
private static final int | WAIT_STATUS_UNKNOWNconstant communicated from native code indicating that a
child died, but it was unable to determine the status |
private static final int | WAIT_STATUS_NO_CHILDRENconstant communicated from native code indicating that there
are currently no children to wait for |
private static final int | WAIT_STATUS_STRANGE_ERRNOconstant communicated from native code indicating that a wait()
call returned -1 and set an undocumented (and hence unexpected) errno |
private final Map | processReferencesMap from pid to Process. We keep weak references to the Process objects
and clean up the entries when no more external references are left. The
process objects themselves don't require much memory, but file
descriptors (associated with stdin/out/err in this case) can be
a scarce resource. |
private final ProcessReferenceQueue | referenceQueueKeeps track of garbage-collected Processes. |
static final ProcessManager | instance |
Methods Summary |
---|
void | cleanUp()Cleans up after garbage collected processes. Requires the lock on the
map.
ProcessReference reference;
while ((reference = referenceQueue.poll()) != null) {
synchronized (processReferences) {
processReferences.remove(reference.processId);
}
}
|
private static native void | close(java.io.FileDescriptor fd)Closes the given file descriptor.
|
static native int | exec(java.lang.String[] commands, java.lang.String[] environment, java.lang.String workingDirectory, java.io.FileDescriptor in, java.io.FileDescriptor out, java.io.FileDescriptor err)Executes a native process. Fills in in, out, and err and returns the
new process ID upon success.
|
java.lang.Process | exec(java.lang.String[] commands, java.lang.String[] environment, java.io.File workingDirectory)Executes a process and returns an object representing it.
FileDescriptor in = new FileDescriptor();
FileDescriptor out = new FileDescriptor();
FileDescriptor err = new FileDescriptor();
String workingPath = (workingDirectory == null)
? null
: workingDirectory.getPath();
// Ensure onExit() doesn't access the process map before we add our
// entry.
synchronized (processReferences) {
int pid;
try {
pid = exec(commands, environment, workingPath, in, out, err);
} catch (IOException e) {
IOException wrapper = new IOException("Error running exec()."
+ " Commands: " + Arrays.toString(commands)
+ " Working Directory: " + workingDirectory
+ " Environment: " + Arrays.toString(environment));
wrapper.initCause(e);
throw wrapper;
}
ProcessImpl process = new ProcessImpl(pid, in, out, err);
ProcessReference processReference
= new ProcessReference(process, referenceQueue);
processReferences.put(pid, processReference);
/*
* This will wake up the child monitor thread in case there
* weren't previously any children to wait on.
*/
processReferences.notifyAll();
return process;
}
|
static java.lang.ProcessManager | getInstance()Gets the process manager.
return instance;
|
private static native void | kill(int pid)Kills the process with the given ID.
|
void | onExit(int pid, int exitValue)Called by {@link #watchChildren()} when a child process exits.
ProcessReference processReference = null;
synchronized (processReferences) {
cleanUp();
if (pid >= 0) {
processReference = processReferences.remove(pid);
} else if (exitValue == WAIT_STATUS_NO_CHILDREN) {
if (processReferences.isEmpty()) {
/*
* There are no eligible children; wait for one to be
* added. The wait() will return due to the
* notifyAll() call below.
*/
try {
processReferences.wait();
} catch (InterruptedException ex) {
// This should never happen.
throw new AssertionError("unexpected interrupt");
}
} else {
/*
* A new child was spawned just before we entered
* the synchronized block. We can just fall through
* without doing anything special and land back in
* the native wait().
*/
}
} else {
// Something weird is happening; abort!
throw new AssertionError("unexpected wait() behavior");
}
}
if (processReference != null) {
ProcessImpl process = processReference.get();
if (process != null) {
process.setExitValue(exitValue);
}
}
|
static native void | staticInitialize()Initializes native static state.
|
native void | watchChildren()Listens for signals from processes and calls back to
{@link #onExit(int,int)}.
|