2009-03-14 2 views
6

В моей программе Java используется ProcessBuilder (с параметром redirectErrorStream установлено true) и имеет цикл, который запускает метод чтения входного потока процессов, который блокирует. Внешняя программа, которую я вызываю, останавливается, ожидая ввода и stdin. Теперь я хочу убить процесс. Разве это не выполняется (в отдельном потоке), вызывающим метод уничтожения процесса, и вызывает метод закрытия входного потока, чтобы остановить метод чтения от блокировки больше, так что мой начальный поток может закончиться его жизнью?Почему блок ввода java inputstream.close()?

По какой-то причине process.getInputStream().close() блоки. Из JavaDoc я не понимаю, почему это может произойти. Кроме того, я не понимаю, почему javadoc говорит: «Метод close из InputStream ничего не делает». (link to javadoc) Может кто-нибудь объяснить это?

Спасибо :-)

+0

Вы уверены, что этого не происходит из-за внешней программы, с которой вы работаете? – Geo

ответ

4

Что касается поведения блокировки, на Java существует известная проблема, которая может вызвать тупик при общении с другим процессом. Я не могу сказать, это то, что вы видите, но это стоит посмотреть. Документ для java.lang.Process говорит:

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

+0

Я рассмотрю это, спасибо – Allanrbo

+0

Я столкнулся с той же проблемой. Есть ли способ справиться с ограниченным размером буфера и, таким образом, избежать блокировки подпроцесса? – JorgeGRC

3

По какой-то причине process.getInputStream(). Close() блоки. Из JavaDoc я не вижу , почему это может произойти. Кроме того, I не понимают, почему javadoc говорит «Метод закрытия метода InputStream делает ничего». (ссылка на javadoc) Может ли кому-то объяснить это?

Если вы посмотрите на Javadoc, вы увидите, что InputStream - абстрактный класс. Предполагается, что подклассы, которые расширяют InputStream, переопределяют метод close() (если это необходимо). Очевидно, что подкласс InputStream, который вы используете, делает что-то в методе close.

+0

конечно, это разумно. Я не заметил, что входной поток был абстрактным, спасибо. – Allanrbo

3

Добавляя к тому, что написал jdigital, отметьте это article. Он имеет дело с методом Runtime.exec(), и ProcessBuilder был представлен на Java 5, но мне кажется, что обсуждение может быть экстраполировано на системные процессы в целом.

3

Я думаю, что я понял это. Очевидно, важно вызвать process.getOutputStream(). Close() перед process.getInputStream(). Close() и process.getErrorStream(). Close().

+0

Почему важно закрыть выходной поток перед входным потоком? – Michael

+0

Извините, я имел в виду «по-видимому». Я никогда не понял, почему ... – Allanrbo

+0

Спасибо :) Я задам новый вопрос о SO об этом ... – Michael

-1

У меня была такая же проблема, и после довольно многого боя нашел решение, которое заключается в использовании InputStream#available() перед чтением чего-либо от Process потоков. Доступен фрагмент моего решения here.

+0

Парень, который проголосовал, может объяснить его точку. –

+0

Я не спустил вас вниз, но я не думаю, что это правильно. Вызов 'available()' сообщает вам, сколько данных Java уже прочитало или знает. Это вполне возможно, что больше было написано в буферах ОС, и Java еще не успел их увидеть. Быстрый тест подтвердил, что 'available()' не фиксирует всю длину очень длинной строки 'echo'ed. – dimo414