ランタイムexecとカスタムビルドRTFエディター
-
06-07-2019 - |
質問
RTFドキュメントの作成を管理するクラスと、表示用のXMLファイルでRTFエディターを呼び出すそのクラスのメソッドがあります。
1人のユーザーを除くすべてのユーザーが問題なくこのエディターにアクセスできます。この1人のユーザーは、アプリケーションがハングするだけの問題に常に遭遇します。どのログにもエラーはありません。通常、この種の問題は簡単に特定、再現、修正されますが、私はそれを再現することはできませんので、デバッグの試みは失敗します。
基本的にコードは次のとおりです。
int exitVal = CUBSRTFEditor.runRTFEditor("c:\\tmp\\control"+ap_doc_id+".xml", xml,"I:\\AppealsLetters.exe /process \"c:\\tmp\\control"+ap_doc_id+".xml\"");
public static int runRTFEditor(String xmlLocation, String xmlContent, String executePath)
{
int exitVal = 0;
createLocalFile(xmlLocation, xmlContent);
try
{
System.out.println("executePath must = "+executePath);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(executePath);
System.out.println("after executePath runs");
//exhaust that stream before waiting for the process to exit
InputStream inputstream = proc.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
// read the ls output
String line;
while ((line = bufferedreader.readLine())!= null)
{
System.out.println(line);
}
exitVal = proc.waitFor();
}
catch (Throwable t)
{
t.printStackTrace();
}
CUBSRTFEditor.deleteTempFile(xmlLocation);
return exitVal;
}
最後の出力は最初のSystem.outです。 xmlファイルを取得して他のPCで実行すると、問題なく実行されます。 proc.getErrorStream()またはproc.getOutputStream()に有用な情報がありません。
この問題に関するJDKのJavadocドキュメント(execのハング): 一部のネイティブプラットフォームは標準の入力および出力ストリームに限られたバッファーサイズしか提供しないため、サブプロセスの入力ストリームの書き込みまたは出力ストリームの読み取りに失敗すると、サブプロセスがブロックされ、デッドロックさえ発生する可能性があります。
プロセスが終了するのを待つ前にそのストリームを使い果たしますが、それはそのポイントに到達しないように見えるので助けにはならないようです(2番目のSystem.outは表示されません)
これを間違って実装しましたか?重要なものが欠けていますか?プロセスからより多くの情報を取得する方法についてのアイデアは素晴らしいでしょう。
立ち往生しています...
解決
Runtime.exec()は、一見厄介な小さなスパッドです。 この記事(古いが、まだ関連がある)非常に役立つ。ガンカブルなサンプルコードについては、常に4ページにスキップできます。 :-)
一見すると、コードはproc.getOutputStream()とproc.getErrorStream()の両方を処理する必要があります。これは、これらのストリームを別々のスレッドで処理する正当な理由です。
他のヒント
変更は本番環境に反映され、機能したため、これを更新したかったのです。 BlairHippoの提案に基づいて、匿名の内部クラスと連携して、エラーストリームと入力ストリームの両方を使い果たすための個別のスレッドを作成するようにしました。
new Thread(new Runnable(){
public void run()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line;
while ((line = br.readLine())!= null)
{
System.out.println(line);
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}).start();