1

我有一个管理 RTF 文档创建的类和该类中的一个方法,该方法使用 XML 文件调用 RTF 编辑器进行显示。

除一位用户外,所有用户都可以毫无问题地访问此编辑器。这个用户一直遇到他们的应用程序挂起的问题。任何日志中都没有错误。通常这种问题很容易识别、重现和纠正,但是,我不能在我的生命周期内重现它,所以我的调试尝试失败了。

基本上代码如下:

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挂起): 由于一些原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能会导致子进程阻塞,甚至陷入僵局。

我尝试在等待进程退出之前耗尽该流,但这似乎没有帮助,因为它似乎永远不会达到这一点(第二个 System.out 未显示)

我是否错误地实施了这一点?我错过了什么重要的东西吗?关于如何从流程中获取更多信息的任何想法都会很棒。

我被困住了......

4

2 回答 2

2

Runtime.exec() 是一个看似讨厌的小土豆。我发现这篇文章(旧的,但仍然相关)很有帮助。您可以随时跳到第 4 页以获取一些高度可 gankable 的示例代码。:-)

乍一看,您的代码需要同时处理 proc.getOutputStream() 和 proc.getErrorStream(),这是在单独的线程中处理这些流的一个很好的理由。

于 2009-05-06T18:07:41.907 回答
0

我想对此进行更新,因为该更改今天已进入生产环境并且有效。根据 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();
于 2009-05-13T20:12:57.060 回答