2009-03-14 22 views
6

Mi programa Java usa ProcessBuilder (con redirectErrorStream set true) y tiene un bucle que ejecuta el método de lectura de inputstream de los procesos, que es de bloqueo. El programa externo que estoy llamando deja de esperar la entrada y el stdin. Ahora quiero matar el proceso. ¿No se hace esto (en un hilo separado) llamando al método de destrucción del proceso y llamando al método de cierre de inputstream para evitar que el método de lectura bloquee más, de modo que mi hilo inicial pueda terminar con su vida útil?¿por qué bloquea el inputtream.close() de java?

Por alguna razón process.getInputStream().close() bloques. Desde JavaDoc no veo por qué puede suceder esto. Además, no entiendo por qué el javadoc dice "El método cercano de InputStream no hace nada". (link to javadoc) ¿Podría alguien explicar esto?

Gracias :-)

+0

¿Está seguro de que esto no ocurre debido al programa externo que está ejecutando? – Geo

Respuesta

4

En cuanto al comportamiento de bloqueo, existe un problema conocido en Java que puede causar interbloqueo al comunicarse con otro proceso. No puedo decir si esto es lo que estás viendo, pero vale la pena investigarlo. El documento de java.lang.Process dice:

Debido a que algunas plataformas nativas solamente proporcionan tamaño del búfer limitado para flujos de entrada y de salida estándar, fracaso para escribir rápidamente el flujo de entrada o leer el flujo de salida de el subproceso puede causar el subproceso para bloquear e incluso punto muerto.

+0

Lo investigaré, gracias – Allanrbo

+0

Me encontré con el mismo problema. ¿Hay alguna manera de lidiar con el tamaño limitado del búfer y así evitar el bloqueo del subproceso? – JorgeGRC

3

Por alguna razón process.getInputStream(). Close() bloques. Desde el JavaDoc no veo por qué esto puede suceder. Además, I no entiendo por qué el javadoc dice "El método de cierre de InputStream no hace nada ". (enlace a javadoc) ¿Podría alguien explicar esto?

Si observa el Javadoc, verá que InputStream es una clase abstracta. Se espera que las subclases que extienden InputStream anulen el método close() (si fuera necesario). Claramente, la subclase InputStream que está utilizando hace algo en el método de cierre.

+0

por supuesto, eso tiene sentido. No noté que inputstream era abstracto, gracias. – Allanrbo

3

Agregando a lo que escribió jdigital, marque article. Se trata del método Runtime.exec(), y ProcessBuilder se introdujo en Java 5, pero me parece que la discusión se puede extrapolar a los procesos del sistema en general.

3

Creo que lo descubrí. Obviamente, es importante llamar a process.getOutputStream(). Close() antes de process.getInputStream(). Close() y process.getErrorStream(). Close().

+0

¿Por qué es importante cerrar la secuencia de salida antes de la secuencia de entrada? – Michael

+0

lo siento, quise decir "aparentemente". Nunca me di cuenta de por qué ... – Allanrbo

+0

Gracias :) Voy a hacer una nueva pregunta sobre SO al respecto ... – Michael

-1

Tuve el mismo problema y después de mucho luchar, encontré una solución, que consiste en usar InputStream#available() antes de leer cualquier cosa en Process transmisiones. Un fragmento de mi solución está disponible here.

+0

El hombre que votó en contra podría quizás explicar su punto. –

+0

No te he rechazado, pero no creo que esto sea correcto. Llamar a 'available() 'le indica la cantidad de datos que Java ya ha leído o conoce. Es muy posible que se haya escrito más en los búferes del sistema operativo y Java aún no ha tenido la oportunidad de verlos. Una prueba rápida verificó que 'available()' no captura la longitud completa de una cadena 'echo'ed muy larga. – dimo414

Cuestiones relacionadas