0

プロセスを実行する次のコードがあり、実行中に例外が発生したかどうかを知りたいです。理由もなくハングアップします

Runtime runtime = Runtime.getRuntime();
proc = runtime.exec(command.toString());
ProcessHandler errorStream = new ProcessHandler(proc.getErrorStream(),"ERROR", rdyFilePath);
ExecutorService pool = Executors.newSingleThreadExecutor();
Future future = pool.submit(errorStream);
pool.shutdown();

try {
     if(future.get() == null) {
         log.info("Done completing error thread");
     }
} catch (InterruptedException | ExecutionException e) {
     e.printStackTrace();
}

プロセスハンドラのクラスは次のとおりです

public class ProcessHandler implements Callable<Integer> {

    private static Logger log = Logger.getLogger(ProcessHandler.class.getName());

    InputStream inpStr;
    String strType;
    String rdyFile;


    public ProcessHandler(InputStream inpStr, String strType, String rdyFile) {
        this.inpStr = inpStr;
        this.strType = strType;
        this.rdyFile = rdyFile;
    }

    public Integer call() throws FileMetadataException {
        StringBuffer sb = new StringBuffer();
        try {

            InputStreamReader inpStrd = new InputStreamReader(inpStr);
            BufferedReader buffRd = new BufferedReader(inpStrd);
            String line = null;
            while((line = buffRd.readLine()) != null) {
                if("ERROR".equalsIgnoreCase(strType)) {

                    sb.append(line + "\n");
                    log.info(strType + "->" + line);
                }
            }
            if(sb != null) {
                log.info("Error Stream length : " + sb.length());
                throw new RuntimeException();

            }

            buffRd.close();
        } catch(IOException e) {
            log.error("IOException in ProcessHandler Thread" + e.fillInStackTrace());
            System.err.println(e);
            throw new FileMetadataException();
        } finally {
            if(sb != null) {
                if(sb.toString().length() > 0 ) {
                    log.error("Error string buffer length " + sb.length());
                    // do not create rdy file
                } else {
                    log.error("Error string buffer length : " + sb.length());
                    File f = new File(rdyFile);
                        try {
                            f.createNewFile();
                        } catch(IOException e) {
                            log.error("IOException while creating rdy file");
                        }
                    }
                    // create rdy file. 
                }
            }
            return sb.length();
        }

    }
}
4

2 に答える 2

2

プロセスを実行する次のコードがあり、実行中に例外が発生したかどうかを知りたいです。理由もなくハングアップします

future.get()-- でスローする必要がある例外があった場合、ExecutionException「ハング」しません。例外が出力されていないが、ログまたはコンソール出力で何らかの形で失われていることは確かですか?

コードをたどると、ストリームの読み取りが終了した後にプログラムが終了しない方法がわかりません。エラー ストリームを読み取っているプロセスがまだ実行中で、InputStreamまだ閉じられていない可能性があります。たぶん、出力が多すぎてコアがいっぱいになっている可能性があります(これはbtwStringBufferに変更する必要があります)。StringBuilder

jconsole を使用してアプリケーションにアタッチして、スレッドがまだ実行されているかどうか、実行している場合は何をしているのかを確認できますか?

 if(future.get() == null) {
     log.info("Done completing error thread");
 }

nullしたがって、メソッドから戻った場合にのみ出力がログに記録されますcall()。唯一のリターンは であるため、それは決して起こりませんreturn sb.length();。したがって、例外が発生するcall()か、結果が null 以外になりますInteger

于 2013-09-17T20:22:40.567 に答える
2

Processjavadocから:

一部のネイティブ プラットフォームでは、標準の入力ストリームと出力ストリームに対して限られたバッファー サイズしか提供されないため、サブプロセスの入力ストリームの書き込みまたは出力ストリームの読み取りが迅速に行われないと、サブプロセスがブロックされたり、デッドロックが発生したりする可能性があります。

この警告によるとfuture.get()、プロセス オブジェクトからのエラー ストリームのみを使用しているため、メソッドがハングしています。これまでにProcessオブジェクトを利用したすべてのプラットフォームで、エラーと標準の両方の出力ストリームを使用する必要があることに気付きました。

これは、マルチスレッド アプローチを使用して、プロセスのストリームが確実に消費されるようにする優れたツールです。

この場合、プロセスの標準出力を気にしていないように見えるので、StreamHelperクラスを借用して、次のようなものを追加できます。

StreamHelper inStreamHelper = new StreamHelper(proc.getInputStream());
inStreamHelper.start();
于 2013-09-17T22:24:20.920 に答える