Я подозреваю, что проблема в том, что внешний процесс (подключенный к proc
) либо
- не читает свой стандартный ввод или
- записывает в стандартный вывод данные, которые не читает приложение Java.
Имейте в виду, что Java взаимодействует с внешним процессом с помощью пары «каналов», и они имеют ограниченный объем буферизации. Если вы превысите буферную емкость канала, процесс записи будет заблокирован при записи в канал до тех пор, пока процесс чтения не прочитает достаточно данных из канала, чтобы освободить место. Если читатель не читает, конвейер блокируется.
Если бы вы предоставили больше контекста (например, часть приложения, которая запускает процесс gzip), я мог бы быть более определенным.
Followup
gzip.exe - это утилита unix в используемых нами окнах. gzip.exe в командной строке работает нормально. Но не с помощью программы Java. Есть ли способ, которым мы можем увеличить размер буферизации, который Java записывает в канал. Я обеспокоен входной частью в настоящее время.
В UNIX утилита gzip обычно используется одним из двух способов:
gzip file
сжимает file
, превращая его в file.gz
.
... | gzip | ...
(или что-то подобное), который записывает сжатую версию своего стандартного ввода в свой стандартный вывод.
Я подозреваю, что вы делаете эквивалент последнего, с приложением java как источником ввода команды gzip
и местом назначения ее вывода. И это именно тот сценарий, который может заблокировать ... если Java-приложение не реализовано правильно. Например:
Process proc = Runtime.exec(...); // gzip.exe pathname.
OutputStream out = proc.getOutputStream();
while (...) {
out.write(...);
}
out.flush();
InputStream in = proc.getInputStream();
while (...) {
in.read(...);
}
Если на этапе записи приложения выше записывается слишком много данных, он гарантированно блокируется.
Связь между Java-приложением и gzip
осуществляется по двум каналам. Как я уже говорил выше, канал буферизует определенный объем данных, но этот объем относительно невелик и, безусловно, ограничен. Это причина блокировки. Вот что происходит:
- Процесс
gzip
создается с помощью пары каналов, соединяющих его с процессом приложения Java.
- Приложение Java записывает данные в свой
out
поток
- Процесс
gzip
читает эти данные со своего стандартного ввода, сжимает их и записывает в стандартный вывод.
- Шаги 2. и 3. повторяются несколько раз, пока, наконец, процессы
gzip
не попытаются выполнить запись в свои стандартные выходные блоки.
То, что происходило, это то, что gzip
записывал в свой выходной канал, но ничего не читало из него. В конце концов, мы достигли точки, когда мы исчерпали буферную емкость выходного канала и осуществили запись в блоки канала.
Тем временем приложение Java все еще записывает в поток out
, и после еще нескольких раундов это тоже блокируется, потому что мы заполнили другой канал.
Единственное решение для приложения Java для чтения и записи одновременно . Простой способ сделать это - создать второй поток и выполнить запись во внешний процесс из одного потока и чтение из процесса в другом.
(Изменение буферизации Java или размеров чтения / записи Java не поможет. Буферизация имеет значение в реализациях конвейеров ОС, и нет способа изменить это с чистой Java, если она вообще есть).