1
1
/*
2
- * Copyright (c) 1995, 2024 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 1995, 2025 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
41
41
42
42
/**
43
43
* {@code Process} provides control of native processes started by
44
- * ProcessBuilder.start and Runtime.exec.
44
+ * {@code ProcessBuilder.start} and {@code Runtime.exec} .
45
45
* The class provides methods for performing input from the process, performing
46
46
* output to the process, waiting for the process to complete,
47
47
* checking the exit status of the process, and destroying (killing)
78
78
* process I/O can also be redirected</a>
79
79
* using methods of the {@link ProcessBuilder} class.
80
80
*
81
- * <p>The process is not killed when there are no more references to
82
- * the {@code Process} object, but rather the process
83
- * continues executing asynchronously.
84
- *
85
81
* <p>There is no requirement that the process represented by a {@code
86
82
* Process} object execute asynchronously or concurrently with respect
87
83
* to the Java process that owns the {@code Process} object.
98
94
* Delegating to the underlying Process or ProcessHandle is typically
99
95
* easiest and most efficient.
100
96
*
97
+ * <h2>Resource Usage</h2>
98
+ * {@linkplain ProcessBuilder#start() Starting a process} uses resources in both the invoking process and the invoked
99
+ * process and for the communication streams between them.
100
+ * The resources to control the process and for communication between the processes are retained
101
+ * until there are no longer any references to the Process or the input, error, and output streams
102
+ * or readers, or they have been closed.
103
+ *
104
+ * <p>The process is not killed when there are no more references to the {@code Process} object,
105
+ * but rather the process continues executing asynchronously.
106
+ * The process implementation closes file descriptors and handles for streams
107
+ * that are no longer referenced to prevent leaking operating system resources.
108
+ * Processes that have terminated or been terminated are monitored and their resources released.
109
+ *
110
+ * <p>Streams should be {@code closed} when they are no longer needed, to avoid delaying
111
+ * releasing the operating system resources.
112
+ * {@code Try-with-resources} can be used to open and close the streams.
113
+ * <p>For example, to capture the output of a program known to produce some output and then exit:
114
+ * {@snippet lang = "java" :
115
+ * List<String> capture(List<String> args) throws Exception {
116
+ * ProcessBuilder pb = new ProcessBuilder(args);
117
+ * Process process = pb.start();
118
+ * try (BufferedReader in = process.inputReader()) {
119
+ * List<String> captured = in.readAllLines();
120
+ * int status = process.waitFor();
121
+ * if (status != 0) {
122
+ * throw new RuntimeException("Process %d: %s failed with %d"
123
+ * .formatted(process.pid(), args, status));
124
+ * }
125
+ * return captured;
126
+ * }
127
+ * }
128
+ * }
129
+ * <p>Stream resources (file descriptor or handle) are always paired; one in the invoking process
130
+ * and the other end of that connection in the invoked process.
131
+ * Closing a stream at either end terminates communication but does not have any direct effect
132
+ * on the other Process. The closing of the stream typically results in the other process exiting.
133
+ *
134
+ * <p> {@linkplain #destroy Destroying a process} signals the operating system to terminate the process.
135
+ * It is up to the operating system to clean up and release the resources of that process.
136
+ * Typically, file descriptors and handles are closed. When they are closed, any connections to
137
+ * other processes are terminated and file descriptors and handles in the invoking process signal
138
+ * end-of-file or closed. Usually, that is seen as an end-of-file or an exception.
139
+ *
101
140
* @since 1.0
102
141
*/
103
142
public abstract class Process {
@@ -127,6 +166,9 @@ public Process() {}
127
166
* then this method will return a
128
167
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
129
168
*
169
+ * <p>The output stream should be {@linkplain OutputStream#close closed}
170
+ * when it is no longer needed.
171
+ *
130
172
* @apiNote
131
173
* When writing to both {@link #getOutputStream()} and either {@link #outputWriter()}
132
174
* or {@link #outputWriter(Charset)}, {@link BufferedWriter#flush BufferedWriter.flush}
@@ -159,9 +201,15 @@ public Process() {}
159
201
* then the input stream returned by this method will receive the
160
202
* merged standard output and the standard error of the process.
161
203
*
204
+ * <p>The input stream should be {@linkplain InputStream#close closed}
205
+ * when it is no longer needed.
206
+ *
162
207
* @apiNote
163
- * Use {@link #getInputStream()} and {@link #inputReader()} with extreme care.
164
- * The {@code BufferedReader} may have buffered input from the input stream.
208
+ * Use either this method or an {@linkplain #inputReader() input reader}
209
+ * but not both on the same {@code Process}.
210
+ * The input reader consumes and buffers bytes from the input stream.
211
+ * Bytes read from the input stream would not be seen by the reader and
212
+ * buffer contents are unpredictable.
165
213
*
166
214
* @implNote
167
215
* Implementation note: It is a good idea for the returned
@@ -185,9 +233,15 @@ public Process() {}
185
233
* then this method will return a
186
234
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
187
235
*
236
+ * <p>The error stream should be {@linkplain InputStream#close closed}
237
+ * when it is no longer needed.
238
+ *
188
239
* @apiNote
189
- * Use {@link #getErrorStream()} and {@link #errorReader()} with extreme care.
190
- * The {@code BufferedReader} may have buffered input from the error stream.
240
+ * Use either this method or an {@linkplain #errorReader() error reader}
241
+ * but not both on the same {@code Process}.
242
+ * The error reader consumes and buffers bytes from the error stream.
243
+ * Bytes read from the error stream would not be seen by the reader and the
244
+ * buffer contents are unpredictable.
191
245
*
192
246
* @implNote
193
247
* Implementation note: It is a good idea for the returned
@@ -208,6 +262,16 @@ public Process() {}
208
262
* If the {@code native.encoding} is not a valid charset name or not supported
209
263
* the {@link Charset#defaultCharset()} is used.
210
264
*
265
+ * <p>The reader should be {@linkplain BufferedReader#close closed}
266
+ * when it is no longer needed.
267
+ *
268
+ * @apiNote
269
+ * Use either this method or the {@linkplain #getInputStream input stream}
270
+ * but not both on the same {@code Process}.
271
+ * The input reader consumes and buffers bytes from the input stream.
272
+ * Bytes read from the input stream would not be seen by the reader and the
273
+ * buffer contents are unpredictable.
274
+ *
211
275
* @return a {@link BufferedReader BufferedReader} using the
212
276
* {@code native.encoding} if supported, otherwise, the
213
277
* {@link Charset#defaultCharset()}
@@ -238,16 +302,21 @@ public final BufferedReader inputReader() {
238
302
* then the {@code InputStreamReader} will be reading from a
239
303
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
240
304
*
305
+ * <p>The reader should be {@linkplain BufferedReader#close closed}
306
+ * when it is no longer needed.
307
+ *
241
308
* <p>Otherwise, if the standard error of the process has been redirected using
242
309
* {@link ProcessBuilder#redirectErrorStream(boolean)
243
310
* ProcessBuilder.redirectErrorStream} then the input reader returned by
244
311
* this method will receive the merged standard output and the standard error
245
312
* of the process.
246
313
*
247
314
* @apiNote
248
- * Using both {@link #getInputStream} and {@link #inputReader(Charset)} has
249
- * unpredictable behavior since the buffered reader reads ahead from the
250
- * input stream.
315
+ * Use either this method or the {@linkplain #getInputStream input stream}
316
+ * but not both on the same {@code Process}.
317
+ * The input reader consumes and buffers bytes from the input stream.
318
+ * Bytes read from the input stream would not be seen by the reader and the
319
+ * buffer contents are unpredictable.
251
320
*
252
321
* <p>When the process has terminated, and the standard input has not been redirected,
253
322
* reading of the bytes available from the underlying stream is on a best effort basis and
@@ -283,6 +352,16 @@ public final BufferedReader inputReader(Charset charset) {
283
352
* If the {@code native.encoding} is not a valid charset name or not supported
284
353
* the {@link Charset#defaultCharset()} is used.
285
354
*
355
+ * <p>The error reader should be {@linkplain BufferedReader#close closed}
356
+ * when it is no longer needed.
357
+ *
358
+ * @apiNote
359
+ * Use either this method or the {@linkplain #getErrorStream error stream}
360
+ * but not both on the same {@code Process}.
361
+ * The error reader consumes and buffers bytes from the error stream.
362
+ * Bytes read from the error stream would not be seen by the reader and the
363
+ * buffer contents are unpredictable.
364
+ *
286
365
* @return a {@link BufferedReader BufferedReader} using the
287
366
* {@code native.encoding} if supported, otherwise, the
288
367
* {@link Charset#defaultCharset()}
@@ -314,10 +393,15 @@ public final BufferedReader errorReader() {
314
393
* then the {@code InputStreamReader} will be reading from a
315
394
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
316
395
*
396
+ * <p>The error reader should be {@linkplain BufferedReader#close closed}
397
+ * when it is no longer needed.
398
+ *
317
399
* @apiNote
318
- * Using both {@link #getErrorStream} and {@link #errorReader(Charset)} has
319
- * unpredictable behavior since the buffered reader reads ahead from the
320
- * error stream.
400
+ * Use either this method or the {@linkplain #getErrorStream error stream}
401
+ * but not both on the same {@code Process}.
402
+ * The error reader consumes and buffers bytes from the error stream.
403
+ * Bytes read from the error stream would not be seen by the reader and the
404
+ * buffer contents are unpredictable.
321
405
*
322
406
* <p>When the process has terminated, and the standard error has not been redirected,
323
407
* reading of the bytes available from the underlying stream is on a best effort basis and
@@ -346,14 +430,17 @@ public final BufferedReader errorReader(Charset charset) {
346
430
/**
347
431
* Returns a {@code BufferedWriter} connected to the normal input of the process
348
432
* using the native encoding.
349
- * Writes text to a character-output stream, buffering characters so as to provide
433
+ * Writes text to a character-output stream, buffering characters to provide
350
434
* for the efficient writing of single characters, arrays, and strings.
351
435
*
352
436
* <p>This method delegates to {@link #outputWriter(Charset)} using the
353
437
* {@link Charset} named by the {@code native.encoding} system property.
354
438
* If the {@code native.encoding} is not a valid charset name or not supported
355
439
* the {@link Charset#defaultCharset()} is used.
356
440
*
441
+ * <p>The output writer should be {@linkplain BufferedWriter#close closed}
442
+ * when it is no longer needed.
443
+ *
357
444
* @return a {@code BufferedWriter} to the standard input of the process using the charset
358
445
* for the {@code native.encoding} system property
359
446
* @since 17
@@ -365,7 +452,7 @@ public final BufferedWriter outputWriter() {
365
452
/**
366
453
* Returns a {@code BufferedWriter} connected to the normal input of the process
367
454
* using a Charset.
368
- * Writes text to a character-output stream, buffering characters so as to provide
455
+ * Writes text to a character-output stream, buffering characters to provide
369
456
* for the efficient writing of single characters, arrays, and strings.
370
457
*
371
458
* <p>Characters written by the writer are encoded to bytes using {@link OutputStreamWriter}
@@ -383,6 +470,9 @@ public final BufferedWriter outputWriter() {
383
470
* ProcessBuilder.redirectInput} then the {@code OutputStreamWriter} writes to a
384
471
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
385
472
*
473
+ * <p>The output writer should be {@linkplain BufferedWriter#close closed}
474
+ * when it is no longer needed.
475
+ *
386
476
* @apiNote
387
477
* A {@linkplain BufferedWriter} writes characters, arrays of characters, and strings.
388
478
* Wrapping the {@link BufferedWriter} with a {@link PrintWriter} provides
@@ -674,11 +764,12 @@ public long pid() {
674
764
* free the current thread and block only if and when the value is needed.
675
765
* <br>
676
766
* For example, launching a process to compare two files and get a boolean if they are identical:
677
- * <pre> {@code Process p = new ProcessBuilder("cmp", "f1", "f2").start();
678
- * Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
679
- * ...
680
- * if (identical.get()) { ... }
681
- * }</pre>
767
+ * {@snippet lang = "java" :
768
+ * Process p = new ProcessBuilder("cmp", "f1", "f2").start();
769
+ * Future<Boolean> identical = p.onExit().thenApply(p1 -> p1.exitValue() == 0);
770
+ * ...
771
+ * if (identical.get()) { ... }
772
+ * }
682
773
*
683
774
* @implSpec
684
775
* This implementation executes {@link #waitFor()} in a separate thread
@@ -695,11 +786,11 @@ public long pid() {
695
786
* External implementations should override this method and provide
696
787
* a more efficient implementation. For example, to delegate to the underlying
697
788
* process, it can do the following:
698
- * <pre>{@code
789
+ * {@snippet lang = "java" :
699
790
* public CompletableFuture<Process> onExit() {
700
791
* return delegate.onExit().thenApply(p -> this);
701
792
* }
702
- * }</pre>
793
+ * }
703
794
* @apiNote
704
795
* The process may be observed to have terminated with {@link #isAlive}
705
796
* before the ComputableFuture is completed and dependent actions are invoked.
0 commit comments