Java在Windows Server 2003上执行wmic命令时陷入无限循环

Java在Windows Server 2003上执行wmic命令时陷入无限循环,java,windows,windows-server-2003,Java,Windows,Windows Server 2003,我正在尝试获取Windows Server 2003计算机上正在运行的进程及其文件路径的列表。我正在使用以下代码尝试这样做: protected Map<String,String> getProcesses() { Map<String,String> processes = new HashMap<String,String>(); try { String line; Process p = null;

我正在尝试获取Windows Server 2003计算机上正在运行的进程及其文件路径的列表。我正在使用以下代码尝试这样做:

protected Map<String,String> getProcesses() {
    Map<String,String> processes = new HashMap<String,String>();
    try {
        String line;
        Process p = null;

        // Windows
        if (OS.indexOf("win") >= 0) {
            p = Runtime.getRuntime().exec("wmic process get description,executablepath");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            LOG.info("Entering while loop");
            while ((line = input.readLine()) != null) {
                LOG.info("blah");
                String[] array = line.split("\\s+");
                if (array.length > 1) {
                    processes.put(array[0], array[1]);
                }
            }
            LOG.info("Exited while loop");
            input.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return processes;
}
protectedmap getprocesss(){
映射进程=新的HashMap();
试一试{
弦线;
进程p=null;
//窗户
如果(OS.indexOf(“win”)>=0){
p=Runtime.getRuntime().exec(“wmic进程获取描述,可执行路径”);
BufferedReader输入=新的BufferedReader(新的InputStreamReader(p.getInputStream());
LOG.info(“输入while循环”);
而((line=input.readLine())!=null){
日志信息(“废话”);
字符串[]数组=line.split(\\s+);
如果(array.length>1){
处理.put(数组[0],数组[1]);
}
}
LOG.info(“在循环期间退出”);
input.close();
}
}捕获(例外e){
e、 printStackTrace();
}
返回过程;
}

程序在while条件下陷入无限循环。“blah”和“退出while循环”从未输出到日志。我已经在我的win7本地机器和服务器上运行了命令提示符中的命令,输出的信息很好。我也在我的本地机器上运行了上面的代码,它也可以正常工作。这似乎是Java和WindowsServer2003之间的一些问题,在过去3个小时的谷歌搜索中,我没有发现。非常感谢您的帮助。

在获取和使用
输入流之前,您需要获取并关闭
输出流。这将向流程确认您已经开始向流程发送输入(在本例中,没有输入)

p.getOutputStream().close();

请记住,在
进程
对象上,
getInputStream()
输入来自进程的输出流,而
getOutputStream()
输出则进入进程的输入流。

请记住
BufferedReader.readLine()
操作将在输入未结束时阻塞,看

p.getOutputStream().close();
我想在for
过程中解释了您的体验:

在某些本机平台上,创建进程的方法可能无法很好地用于特殊进程,例如本机窗口进程、守护进程、Microsoft Windows上的Win16/DOS进程或shell脚本。创建的子流程没有自己的终端或控制台。其所有标准io(即stdin、stdout、stderr)操作将通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从中获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁


所以,当我在服务器上运行它时,在我可以读取它之前,进程的数量会溢出缓冲区?这是可能的。我不熟悉wmic命令,所以我不能确定情况是否如此。另外,@rgetman是对的,您应该正在读取进程OutputStream.Hm,我将尝试
p.getOutputStream().close();BufferedReader输入=新的BufferedReader(新的InputStreamReader(p.getInputStream())并查看它的作用。我很快会回来的。你的回答解决了我3个小时的挠头后的问题。我将把它称为wmic中的一个bug,但我会把这项工作处理掉。谢谢奇怪的是,如果您将wmic输出重定向到一个文件,而不关闭outputstream,它就会工作。这不仅仅是java的问题。在一个vbscript测试案例中,我遇到了同样的问题。在WindowsXP上测试Java应用程序时,遇到了同样的问题。我尝试了许多不同的技术来修复死锁,包括使用stderr、写入缓冲区。这篇文章解决了这个问题。谢谢你。