Process
提供了对由ProcessBuilder.start和Runtime.exec启动的本机进程的控制。该类提供了执行来自进程的输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀死)进程的方法。ProcessBuilder.start()
和Runtime.exec
方法创建一个本机进程并返回Process
的子类的实例,该实例可用于控制进程并获取有关其的信息。
创建进程的方法可能无法很好地处理某些本机平台上的特殊进程,例如本机窗口进程、守护进程、Microsoft Windows上的Win16/DOS进程或shell脚本。
默认情况下,创建的进程没有自己的终端或控制台。所有标准I/O(即stdin、stdout、stderr)操作将被重定向到父进程,可以通过使用方法getOutputStream()
、getInputStream()
和getErrorStream()
获取的流来访问这些操作。字符和行的I/O流可以使用方法outputWriter()
、outputWriter(Charset)
、inputReader()
、inputReader(Charset)
、errorReader()
和errorReader(Charset)
进行写入和读取。父进程使用这些流来向进程提供输入并获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入进程的输入流或读取进程的输出流可能导致进程阻塞,甚至死锁。
如有需要,也可以使用ProcessBuilder类的方法重定向进程I/O。
当没有对Process
对象的更多引用时,进程不会被终止,而是继续异步执行。
不要求由Process
对象表示的进程异步或并发地与拥有Process
对象的Java进程执行。
从1.5开始,ProcessBuilder.start()
是创建Process
的首选方式。
Process的子类应重写onExit()
和toHandle()
方法,以提供一个完全功能的Process,包括进程ID、有关进程的信息、直接子级和进程的直接子级加上这些子级的后代。通常,委托给底层Process或ProcessHandle是最简单且最有效的方法。
- 自:
- 1.0
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionchildren()
返回进程的直接子级的快照。返回进程的后代的快照。abstract void
destroy()
终止进程。强制终止进程。final BufferedReader
返回连接到进程标准错误的BufferedReader
。final BufferedReader
errorReader
(Charset charset) 返回使用Charset连接到此进程标准错误的BufferedReader
。abstract int
返回进程的退出值。abstract InputStream
返回连接到进程错误输出的输入流。abstract InputStream
返回连接到进程正常输出的输入流。abstract OutputStream
返回连接到进程正常输入的输出流。info()
返回有关进程的信息的快照。final BufferedReader
返回连接到进程标准输出的BufferedReader
。final BufferedReader
inputReader
(Charset charset) 返回使用Charset连接到此进程标准输出的BufferedReader
。boolean
isAlive()
测试由此Process
表示的进程是否存活。onExit()
返回用于进程终止的CompletableFuture<Process>
。final BufferedWriter
返回使用本机编码连接到进程正常输入的BufferedWriter
。final BufferedWriter
outputWriter
(Charset charset) 返回使用Charset连接到进程正常输入的BufferedWriter
。long
pid()
返回进程的本机进程ID。boolean
如果destroy()
的实现通常终止进程,则返回true
,如果destroy
的实现强制并立即终止进程,则返回false
。toHandle()
返回进程的ProcessHandle。abstract int
waitFor()
使当前线程等待,直到由此Process
对象表示的进程终止为止。boolean
使当前线程等待,直到由此Process
对象表示的进程终止为止,或者经过指定的等待时间。
-
Constructor Details
-
Process
public Process()Process的默认构造函数。
-
-
Method Details
-
getOutputStream
返回连接到进程正常输入的输出流。将流输出到由此Process
对象表示的进程的标准输入中。如果进程的标准输入已使用
ProcessBuilder.redirectInput
重定向,则此方法将返回一个空输出流。- API注释:
-
在同时写入
getOutputStream()
和outputWriter()
或outputWriter(Charset)
之前,应调用BufferedWriter.flush
。 - 实现注释:
- 实现注释:返回的输出流最好是缓冲的。
- 返回:
- 连接到进程正常输入的输出流
-
getInputStream
返回连接到进程正常输出的输入流。该流从由此Process
对象表示的进程的标准输出中获取数据。如果进程的标准输出已使用
ProcessBuilder.redirectOutput
重定向,则此方法将返回一个空输入流。否则,如果进程的标准错误已使用
ProcessBuilder.redirectError
或ProcessBuilder.redirectErrorStream
重定向,则此方法返回的输入流将接收进程的合并标准输出和标准错误。- API注释:
-
使用
getInputStream()
和inputReader()
时要非常小心。BufferedReader
可能已经缓冲了来自输入流的输入。 - 实现注释:
- 实现注释:返回的输入流最好是缓冲的。
- 返回:
- 连接到进程正常输出的输入流
-
getErrorStream
返回连接到进程错误输出的输入流。该流从由此Process
对象表示的进程的错误输出中获取数据。如果进程的标准错误已使用
ProcessBuilder.redirectError
或ProcessBuilder.redirectErrorStream
重定向,则此方法将返回一个空输入流。- API注释:
-
使用
getErrorStream()
和errorReader()
时要非常小心。BufferedReader
可能已经缓冲了来自错误流的输入。 - 实现注释:
- 实现注释:返回的输入流最好是缓冲的。
- 返回:
- 连接到进程错误输出的输入流
-
inputReader
返回连接到进程标准输出的BufferedReader
。使用本机编码的Charset
读取标准输出的字符、行或流行。此方法委托给使用由
native.encoding
系统属性命名的Charset
的inputReader(Charset)
。如果native.encoding
不是有效的字符集名称或不受支持,则使用Charset.defaultCharset()
。- 返回:
-
使用
native.encoding
(如果支持)连接的BufferedReader
,否则使用Charset.defaultCharset()
- 自:
- 17
-
inputReader
返回一个连接到此进程标准输出的BufferedReader
,使用指定的字符集。这个BufferedReader
可用于读取标准输出的字符、行或流行。字符通过从此进程的
getInputStream()
读取和解码字节的InputStreamReader读取。字节使用指定的charset
解码为字符;对于错误输入和不可映射字符序列,将使用charset的默认替换。BufferedReader
从InputStreamReader读取和缓冲字符。第一次调用此方法会创建一个
BufferedReader
,如果再次使用相同的charset
调用,则会返回相同的BufferedReader
。再次使用不同的charset
调用此方法是错误的。如果进程的标准输出已经使用
ProcessBuilder.redirectOutput
重定向,则InputStreamReader将从一个空输入流读取。否则,如果进程的标准错误已经使用
ProcessBuilder.redirectErrorStream
重定向,则此方法返回的输入读取器将接收进程的合并标准输出和标准错误。- API 注意:
-
同时使用
getInputStream()
和inputReader(Charset)
具有不可预测的行为,因为缓冲读取器会提前从输入流中读取。当进程终止且标准输入未被重定向时,从底层流中可用的字节的读取是尽力而为的,可能是不可预测的。
- 参数:
-
charset
- 用于将字节解码为字符的Charset
- 返回:
-
使用
charset
连接到进程标准输出的BufferedReader
- 抛出:
-
NullPointerException
- 如果charset
为null
-
IllegalStateException
- 如果多次使用不同的charset参数调用 - 自:
- 17
-
errorReader
返回一个连接到进程标准错误的BufferedReader
,使用本机编码的Charset
读取标准错误的字符、行或流行。此方法委托给使用由
native.encoding
系统属性命名的Charset
的errorReader(Charset)
。如果native.encoding
不是有效的字符集名称或不受支持,则使用Charset.defaultCharset()
。- 返回:
-
使用支持的
native.encoding
的BufferedReader
,否则使用Charset.defaultCharset()
- 自:
- 17
-
errorReader
返回一个连接到此进程标准错误的BufferedReader
,使用指定的字符集。这个BufferedReader
可用于读取标准错误的字符、行或流行。字符通过从此进程的
getErrorStream()
读取和解码字节的InputStreamReader读取。字节使用指定的charset
解码为字符;对于错误输入和不可映射字符序列,将使用charset的默认替换。BufferedReader
从InputStreamReader读取和缓冲字符。第一次调用此方法会创建一个
BufferedReader
,如果再次使用相同的charset
调用,则会返回相同的BufferedReader
。再次使用不同的charset
调用此方法是错误的。如果进程的标准错误已经使用
ProcessBuilder.redirectError
或ProcessBuilder.redirectErrorStream
重定向,则InputStreamReader将从一个空输入流读取。- API 注意:
-
同时使用
getErrorStream()
和errorReader(Charset)
具有不可预测的行为,因为缓冲读取器会提前从错误流中读取。当进程终止且标准错误未被重定向时,从底层流中可用的字节的读取是尽力而为的,可能是不可预测的。
- 参数:
-
charset
- 用于将字节解码为字符的Charset
- 返回:
-
使用
charset
连接到进程标准错误的BufferedReader
- 抛出:
-
NullPointerException
- 如果charset
为null
-
IllegalStateException
- 如果多次使用不同的charset参数调用 - 自:
- 17
-
outputWriter
返回一个连接到进程标准输入的使用本机编码的BufferedWriter
。将文本写入字符输出流,缓冲字符以提供对单个字符、数组和字符串的高效写入。此方法委托给使用由
native.encoding
系统属性命名的Charset
的outputWriter(Charset)
。如果native.encoding
不是有效的字符集名称或不受支持,则使用Charset.defaultCharset()
。- 返回:
-
使用
native.encoding
系统属性的字符集连接到进程标准输入的BufferedWriter
- 自:
- 17
-
outputWriter
返回一个连接到进程标准输入的使用指定字符集的BufferedWriter
。将文本写入字符输出流,缓冲字符以提供对单个字符、数组和字符串的高效写入。写入的字符由
OutputStreamWriter
编码为字节,并使用Charset
写入此Process
表示的进程的标准输入。对于错误输入和不可映射字符序列,将使用charset的默认替换。第一次调用此方法会创建一个
BufferedWriter
,如果再次使用相同的charset
调用,则会返回相同的BufferedWriter
。再次使用不同的charset
调用此方法是错误的。如果进程的标准输入已经使用
ProcessBuilder.redirectInput
重定向,则OutputStreamWriter
将写入一个空输出流。- API 注意:
-
BufferedWriter写入字符、字符数组和字符串。将
BufferedWriter
与PrintWriter
结合使用可提供对基本类型和对象的高效缓冲和格式化,以及对换行符自动刷新的支持。调用BufferedWriter.flush()
方法将缓冲的输出刷新到进程。在同时写入
getOutputStream()
和outputWriter()
或outputWriter(Charset)
时,应在写入OutputStream
之前调用BufferedWriter.flush。 - 参数:
-
charset
- 用于将字符编码为字节的Charset
- 返回:
-
使用
charset
连接到进程标准输入的BufferedWriter
- 抛出:
-
NullPointerException
- 如果charset
为null
-
IllegalStateException
- 如果多次使用不同的charset参数调用 - 自:
- 17
-
waitFor
使当前线程等待,直到由此Process
对象表示的进程终止。如果进程已经终止,则此方法立即返回。如果进程尚未终止,则调用线程将被阻塞,直到进程退出。- 返回:
-
由此
Process
对象表示的进程的退出值。按照惯例,值0
表示正常终止。 - 抛出:
-
InterruptedException
- 如果当前线程在等待时被另一个线程中断,则等待将结束并抛出InterruptedException
。
-
waitFor
使当前线程等待,直到表示此Process
对象的进程终止,或经过指定的等待时间为止。如果进程已经终止,则此方法立即返回值
true
。如果进程尚未终止且超时值小于或等于零,则此方法将立即返回值false
。此方法的默认实现轮询
exitValue
以检查进程是否已终止。强烈建议此类的具体实现重写此方法,以提供更高效的实现。- 参数:
-
timeout
- 最长等待时间 -
unit
-timeout
参数的时间单位 - 返回:
-
如果进程已退出,则返回
true
;如果等待时间在进程退出之前已过,则返回false
。 - 抛出:
-
InterruptedException
- 如果当前线程在等待时被中断。 -
NullPointerException
- 如果单位为null - 自版本:
- 1.8
-
exitValue
public abstract int exitValue()返回进程的退出值。- 返回:
-
表示此
Process
对象的进程的退出值。按照惯例,值0
表示正常终止。 - 抛出:
-
IllegalThreadStateException
- 如果表示此Process
对象的进程尚未终止
-
destroy
public abstract void destroy()终止进程。由此Process
对象表示的进程是否支持正常终止
取决于实现。强制进程销毁被定义为立即终止进程,而正常终止允许进程干净地关闭。如果进程不活动,则不执行任何操作。当进程终止时,
onExit()
返回的CompletableFuture
将被完成。 -
destroyForcibly
强制终止进程。由此Process
对象表示的进程将被强制终止。强制进程销毁被定义为立即终止进程,而正常终止允许进程干净地关闭。如果进程不活动,则不执行任何操作。当进程终止时,
onExit()
返回的CompletableFuture
将被完成。在由
ProcessBuilder.start()
和Runtime.exec(java.lang.String)
返回的Process
对象上调用此方法将强制终止进程。- API注释:
-
进程可能不会立即终止。即在调用
destroyForcibly()
后,isAlive()
可能会在短暂时间内返回true。如果需要,可以将此方法链接到waitFor()
。 - 实现要求:
-
此方法的默认实现调用
destroy()
,因此可能不会强制终止进程。 - 实现说明:
- 强烈建议此类的具体实现重写此方法,以提供符合规范的实现。
- 返回:
-
表示被强制销毁的进程的
Process
对象 - 自版本:
- 1.8
-
supportsNormalTermination
public boolean supportsNormalTermination()如果destroy()
的实现是正常终止进程,则返回true
;如果destroy
的实现强制并立即终止进程,则返回false
。在由
ProcessBuilder.start()
和Runtime.exec(java.lang.String)
返回的Process
对象上调用此方法,根据平台实现返回true
或false
。- 实现要求:
-
此实现抛出一个
UnsupportedOperationException
实例,并不执行其他操作。 - 返回:
-
如果
destroy()
的实现是正常终止进程,则返回true
;否则,destroy()
将强制终止进程 - 抛出:
-
UnsupportedOperationException
- 如果Process实现不支持此操作 - 自版本:
- 9
-
isAlive
public boolean isAlive()检查由此Process
表示的进程是否仍在运行。- 返回:
-
如果由此
Process
对象表示的进程尚未终止,则返回true
。 - 自版本:
- 1.8
-
pid
public long pid()返回进程的本机进程ID。本机进程ID是操作系统分配给进程的标识号。- 实现要求:
-
此方法的实现将进程ID作为
toHandle().pid()
返回。 - 返回:
- 进程的本机进程ID
- 抛出:
-
UnsupportedOperationException
- 如果Process实现不支持此操作 - 自版本:
- 9
-
onExit
返回一个用于处理进程终止的CompletableFuture<Process>
。CompletableFuture
提供了在进程终止时触发依赖函数或操作的能力,这些函数或操作可以同步或异步运行。当进程终止时,无论进程的退出状态如何,CompletableFuture
都将完成
。调用
onExit().get()
会等待进程终止并返回进程。该future可用于检查进程是否完成或等待进程终止。取消CompletableFuture
不会影响进程。由
ProcessBuilder.start()
返回的进程会覆盖默认实现,以提供一种有效的等待进程退出的机制。- API注释:
-
使用
onExit
是waitFor
的一种替代方法,它既能实现额外的并发性,又能方便地访问进程的结果。可以使用Lambda表达式来评估进程执行的结果。如果在使用值之前需要执行其他处理,则onExit
是一种方便的机制,可以释放当前线程,并仅在需要值时阻塞。
例如,启动一个进程来比较两个文件并获取它们是否相同的布尔值:Process p = new ProcessBuilder("cmp", "f1", "f2").start(); Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0); ... if (identical.get()) { ... }
CompletableFuture
完成和依赖操作被调用之前,可以观察到进程已终止。 - 实现要求:
-
此实现在单独的线程中重复执行
waitFor()
,直到成功返回。如果waitFor
的执行被中断,线程的中断状态将被保留。当
waitFor()
成功返回时,CompletableFuture
将完成,无论进程的退出状态如何。如果同时等待大量进程,此实现可能会消耗大量内存用于线程堆栈。外部实现应重写此方法并提供更高效的实现。例如,要委托给底层进程,可以执行以下操作:
public CompletableFuture<Process> onExit() { return delegate.onExit().thenApply(p -> this); }
- 返回:
-
用于进程的新
CompletableFuture<Process>
- 自版本:
- 9
-
toHandle
返回进程的ProcessHandle
。由ProcessBuilder.start()
和Runtime.exec(java.lang.String)
返回的Process
对象实现toHandle
,相当于ProcessHandle.of(pid)
,包括对SecurityManager和RuntimePermission("manageProcess")
的检查。- 实现要求:
-
此实现会抛出一个
UnsupportedOperationException
的实例,并不执行其他操作。子类应该重写此方法以提供进程的 ProcessHandle。除非被重写,pid()
、info()
、children()
和descendants()
这些方法会操作 ProcessHandle。 - 返回:
- 返回一个进程的 ProcessHandle
- 抛出:
-
UnsupportedOperationException
- 如果进程实现不支持此操作 -
SecurityException
- 如果安装了安全管理器并且它拒绝 RuntimePermission("manageProcess") - 自 JDK 版本:
- 9
-
info
返回有关进程的信息快照。如果可用,
ProcessHandle.Info
实例具有访问器方法,返回有关进程的信息。- 实现要求:
-
此实现将进程的信息返回为:
toHandle().info()
。 - 返回:
- 有关进程的信息快照,始终非空
- 抛出:
-
UnsupportedOperationException
- 如果进程实现不支持此操作 - 自 JDK 版本:
- 9
-
children
- 实现要求:
-
此实现将直接子进程返回为:
toHandle().children()
。 - 返回:
- 一个顺序的 ProcessHandles 流,表示该进程的直接子进程
- 抛出:
-
UnsupportedOperationException
- 如果进程实现不支持此操作 -
SecurityException
- 如果安装了安全管理器并且它拒绝 RuntimePermission("manageProcess") - 自 JDK 版本:
- 9
-
descendants
- 实现要求:
-
此实现将所有子进程返回为:
toHandle().descendants()
。 - 返回:
- 一个顺序的 ProcessHandles 流,表示该进程的后代
- 抛出:
-
UnsupportedOperationException
- 如果进程实现不支持此操作 -
SecurityException
- 如果安装了安全管理器并且它拒绝 RuntimePermission("manageProcess") - 自 JDK 版本:
- 9
-