Java ProcessBuilder: Résultante De Processus Se Bloque
J'ai essayé de l'utilisation de Java ProcessBuilder de lancer une application sous Linux qui doit s'exécuter à "long terme". La façon dont ce programme est de lancer une commande (dans ce cas, je suis en train de lancer un média application de lecture), de lui permettre d'exécuter et vérifier pour s'assurer qu'il n'a pas écrasé. Par exemple, vérifier pour voir si le PID est toujours actif, et ensuite relancer le processus, si il est mort.
Le problème, je vais passer maintenant, c'est que le PID reste vivant dans le système, mais l'interface graphique de l'application se bloque. J'ai essayé de déplacer le ProcessBuilder(cmd).démarrer() dans un thread séparé, mais qui ne semble pas être la résolution de n'importe quoi, comme j'ai espéré qu'il aurait.
Fondamentalement le résultat est que, pour l'utilisateur, le programme SEMBLE avoir écrasé, tuant le processus Java que les lecteurs de la ProcessBuilder.start() Processus permet en fait le Processus créé pour reprendre son comportement normal. Cela signifie que quelque chose dans l'application Java est interférant avec les Processus générés dynamiquement, mais je n'ai absolument aucune idée de ce que, à ce stade. (C'est pourquoi j'ai essayé de séparer dans un autre thread, ce qui ne semble pas résoudre quoi que ce soit)
Si quelqu'un a des entrée/pensées, s'il vous plaît laissez-moi savoir, que je ne peux pas pour la vie de me faire penser à la façon de résoudre ce problème.
Edit: je n'ai aucune inquiétude sur le flux d'e/S créé à partir du Processus, et ont donc pris aucune mesure de traiter avec que-ce que cela pourrait provoquer un blocage dans le Processus lui-même?
- Puisque vous avez déjà dit que vous n'êtes pas affaire avec les flux du processus, je dois carillon pour dire que "Oui, il est fortement probable que c'est la cause du problème. Il est important de lire le contenu de stdout et stderr, et aussi écrire à stdin si l'enfant attend de vous". Il serait utile de votre temps pour vérifier ce DONC, la question: stackoverflow.com/questions/882772/...
Vous devez vous connecter pour publier un commentaire.
Si le processus écrit
stderr
oustdout
, et vous n'êtes pas le lire - il vient de "l'accrocher" , le blocage lors de l'écriture destdout/err
. Redirigerstdout/err
à/dev/null
à l'aide d'une coquille ou de fusionstdout/err
avec redirectErrorStream(vrai) et de générer un autre thread qui lit à partir destdout
du processusVous voulez la truc?
Ne pas commencer votre processus de ProcessBuilder.start(). N'essayez pas de jouer avec les flux de redirection/consommation de Java (surtout si vous ne passez pas de s**t à ce sujet ; )
Utilisation ProcessBuilder.start() pour commencer un petit script shell qui gobe tous les flux d'entrées-sorties.
Quelque chose comme ça:
Qui est: si vous n'avez pas de soins sur stdout et encore envie de journal stderr (pensez-vous?) pour un fichier (erreur.journal ici).
Si vous ne se soucient même pas stderr, juste rediriger vers stdout:
Et que vous appelez ce petit script à partir de Java, en lui donnant comme argument le nom du processus que vous souhaitez exécuter.
Si un processus s'exécutant sur Linux qui est de la redirection des deux stdout et stderr vers /dev/null encore produire rien alors vous avez cassé, non conforme, à l'installation de Linux 😉
En d'autres mots: le ci-dessus Fonctionne, tout Simplement [TM] et de se débarrasser de la problématique "vous avez besoin de consommer les cours d'eau dans le présent et que l'ordre bla bla bla Java spécifiques non-sens".
Le thread qui exécute le processus peut bloquer si il ne gère pas la sortie. Cela peut être fait en créant un nouveau thread qui lit la sortie du processus.
Viens de tombé sur cette après j'ai eu un problème similaire. En accord avec nos, vous avez besoin pour gérer la sortie. J'ai eu quelque chose comme ceci:
et il a été génial de travailler. Le processus générés dynamiquement même fait une sortie certains de sortie, mais pas beaucoup. Quand j'ai commencé à la sortie beaucoup plus, il est apparu mon processus n'était pas encore arriver a lancé plus. J'ai mis à jour à:
et il a commencé à travailler à nouveau. (Reportez-vous à cette lien pour convertStreamToStr (code)
Si vous ne lisez pas les flux de sortie créé par le processus, alors il est possible que l'application bloc une fois que l'application de tampons sont pleins. Je n'ai jamais vu cela se produire sur Linux (bien que je ne dis pas qu'il n'est pas), mais j'ai vu exactement ce problème sur Windows. Je pense que c'est probablement lié.
JDK7 aura la prise en charge intégrée pour les sous-processus redirection d'e/S:
http://download.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
En attendant, si vous voulez vraiment jeter stdout/stderr, il semble meilleur (sur Linux) pour invoquer ProcessBuilder sur une commande qui ressemble à:
Dans le cas où vous avez besoin pour capturer la sortie standard stdout et stderr et surveiller le processus, puis en utilisant Apache Commons Exec m'a beaucoup aidé.
Je crois que le problème est la mise en mémoire tampon tuyau de Linux lui-même.
Essayez d'utiliser
stdbuf
avec votre exécutableLa
-o0
dit de ne pas le tampon de sortie.Il en va de même pour
-i0
et-e0
si vous souhaitez annuler les tampons de l'entrée d'erreur et le tuyau.Une autre solution consiste à démarrer le processus avec
Redirect.PIPE
et fermer laInputStream
comme ceci:J'ai testé sous Windows et Linux, et ça marche!