Reputation: 109
I want to execute a specific shell command on a Linux machine with Java. So I found a tutorial by/from baeldung.com.
My problem is that even the example command (process) never finishes.
private static class StreamGobbler implements Runnable {
private InputStream inputStream;
private Consumer<String> consumer;
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}
@Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines()
.forEach(consumer);
}
}
boolean isWindows = System.getProperty("os.name")
.toLowerCase().startsWith("windows");
String homeDirectory = System.getProperty("user.home");
Process process;
if (isWindows) {
process = Runtime.getRuntime()
.exec(String.format("cmd.exe /c dir %s", homeDirectory));
} else {
process = Runtime.getRuntime()
.exec(String.format("sh -c ls %s", homeDirectory));
}
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;
Hope that somebody has an idea.
Upvotes: 0
Views: 318
Reputation: 159086
When you call Executors.newSingleThreadExecutor()
, a background thread is started. Since the thread is not a daemon thread, the JVM will not terminate until the thread stops running. That never happens, so your Java program keeps running, even though the main
thread has terminated.
There are multiple ways of fixing it:
Don't use an executor, just start a thread, which will end when the run()
method of StreamGobbler
ends.
StreamGobbler streamGobbler = ...
new Thread(streamGobbler).start();
int exitCode = process.waitFor();
Shut down the executor when you're done with it.
StreamGobbler streamGobbler = ...
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(streamGobbler);
int exitCode = process.waitFor();
executor.shutdown();
Upvotes: 4