Подпроцесс, запущенный из Java, завершается с использованием waitFor, но потоки не прекращаются - PullRequest
6 голосов
/ 19 сентября 2011

Я использую Java ProcessBuilder для запуска подпроцесса, который является еще одной программой Java, которая должна запускаться в отдельной JVM.

Я запускаю два потока для чтения из потоков stdout и stderr из процесса, чтобы не было зависаний, если буферные буферы заполнены. Вызов Process.waitFor возвращается, но потоки не прекращаются.

Код, который я использую, выглядит примерно так (команда представляет собой список строк):

ProcessBuilder pb = new ProcessBuilder(command);

final Process p = pb.start();
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
final ByteArrayOutputStream errStream = new ByteArrayOutputStream();

Thread outputThread = new Thread() {
    @Override
    public void run() {
        try {
            IOUtils.copy(p.getInputStream(), outStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    };
};
outputThread.start();

Thread errorThread = new Thread() {
    @Override
    public void run() {
        try {
            IOUtils.copy(p.getErrorStream(), errStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    };
};
errorThread.start();

int returncode = p.waitFor();
outputThread.join();
errorThread.join();

Если я запускаю что-то еще, например, «java -version» или «dir» или что-то еще, код работает нормально. У меня есть доступ к коду Java, который я пытаюсь запустить, но я никогда не слышал, чтобы вы вызывали close () для System.out.

Ответы [ 2 ]

3 голосов
/ 27 сентября 2011

Apache commons exec делает все это за вас.Гораздо проще сделать ...

http://commons.apache.org/exec/

0 голосов
/ 19 сентября 2011

Как я знаю из этого сайта , вы должны самостоятельно закрыть все std-потоки из объекта Process. Независимо от того, используется ли раньше или нет. Кажется, это тесно связано с сборщиком мусора G1 (по умолчанию начиная с Java 7 afaik), который сохраняет каналы открытыми, если они не закрыты явно - даже когда подпроцесс завершен.

Я не знаком с внутренними компонентами здесь, но код, который я разместил в мой ответ на мой вопрос, прекрасно работает в системе 24/7, которая часто вызывает GhostScript и другие.

Другие вопросы и ответы по SO, утверждающие, что вы должны явно закрыть std-потоки Process:

...