Java зависает при попытке закрыть ProcessBuilder OutputStream - PullRequest
2 голосов
/ 06 мая 2010

У меня есть следующий код Java, чтобы запустить ProcessBuilder, открыть OutputStream, заставить процесс записать строку в OutputStream, а затем закрыть OutputStream.Все это зависает бесконечно, когда я пытаюсь закрыть OutputStream.Это происходит только в Windows, но не в Mac или Linux.

Некоторые из связанных вопросов, кажется, близки к той же проблеме, что и у меня, но я не смог выяснить, как применитьответы на мою проблему, так как я относительный новичок с Java.Вот кодВы можете видеть, что я вставил много операторов println, чтобы попытаться изолировать проблему.

    System.out.println("GenMic trying to get the input file now");
    System.out.flush();
    OutputStream out = child.getOutputStream();
    try {
        System.out.println("GenMic getting ready to write the input file to out");
        System.out.flush();
        out.write(intext.getBytes());  // intext is a string previously created
        System.out.println("GenMic finished writing to out");
        System.out.flush();
        out.close();
        System.out.println("GenMic closed OutputStream");
        System.out.flush();
    } catch (IOException iox) {
        System.out.println("GenMic caught IOException 2");
        System.out.flush();
        String detailedMessage = iox.getMessage();
        System.out.println("Exception: " + detailedMessage);
        System.out.flush();
        throw new RuntimeException(iox);
    }

И вот вывод, когда этот блок выполняется:

GenMic пытается получитьвходной файл теперь

GenMic готовится записать входной файл в

GenMic завершил запись в

Ответы [ 3 ]

3 голосов
/ 06 мая 2010

Необходимо убедиться, что потоки, возвращаемые getInputStream() и getOutputStream(), используются в отдельных потоках, и эти потоки отличаются от тех, в которых вы закрываете поток, возвращаемый getOutputStream().

Обычно требуется иметь как минимум 3 потока на подпроцесс, если вы хотите манипулировать и исследовать его stdin , stdout и stderr . В зависимости от ваших обстоятельств один из потоков может быть вашим текущим потоком выполнения (тем, в котором вы создаете ProcessBuilder).

3 голосов
/ 06 мая 2010

Когда это случилось со мной, это произошло потому, что я не прочитал все из потока, в который процесс записал.

Документы API для класса java.lang.Process говорят:

Созданный подпроцесс не имеет собственного терминала или консоли. Все его стандартные операции io (т.е. stdin, stdout, stderr) будут перенаправлены на родительский процесс через три потока (getOutputStream (), getInputStream (), getErrorStream ()). Родительский процесс использует эти потоки для подачи входных данных и получения выходных данных из подпроцесса. Поскольку некоторые собственные платформы предоставляют ограниченный размер буфера только для стандартных входных и выходных потоков, невозможность оперативной записи входного потока или чтения выходного потока подпроцесса может привести к блокировке подпроцесса и даже к тупиковой блокировке.

Я бы попытался вызвать getInputStream () для экземпляра Process и написать цикл для чтения по одному байту за раз, пока он не достигнет EOF. И я бы сделал то же самое с getErrorStream () на всякий случай, если процесс пишет в stderr.

1 голос
/ 06 мая 2010

У вас есть что-нибудь читающее из stdout / stderr процесса?

Вполне вероятно, что процесс пытается что-то вывести, но блокируется, поскольку никто не читает вывод. Это означает, что ваши блоки out.flush() или out.close() как процесс не могут обойти обработку входных данных, поскольку он заблокировал выполнение вывода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...