java执行cmd命令出现堵塞现象的解决方法


这些是其他博客的片段...


发现问题的过程是这样的,我使用staf在远程的机器上执行命令,并且需要获取远程命令执行的返回值。因此写了如下代码。其中"staf " + ipAddress + " process query handle " + handle是获取staf具体的handle信息。如:staf 9.12.207.120 process query handle 89,具体输出的信息应该如下,因此process的return code应该是1,可是debug的时候发现程序一直hang在那里,一直在抛出IllegalThreadStateException之后休眠然后循环, hung了很久都没有返回。


具体的就不多帖代码了,反正就是java执行cmd命令时候出现堵塞现象。


google原因查到API中有说到

http://docs.oracle.com/javase/1.5.0/docs/api/

    The ProcessBuilder.start()and Runtime.exec methods create a native process and return aninstance of a subclass of Process that can be used tocontrol the process and obtain information about it. The classProcess provides methods for performing input from theprocess, performing output to the process, waiting for the processto complete, checking the exit status of the process, anddestroying (killing) the process.

    Themethods that create processes may not work well for specialprocesses on certain native platforms, such as native windowingprocesses, daemon processes, Win16/DOS processes on MicrosoftWindows, or shell scripts. Thecreated subprocess does not have its own terminal orconsole. All its standard io (i.e. stdin, stdout, stderr)operations will be redirected to the parent processthrough three streams (getOutputStream(),getInputStream(),getErrorStream()).The parent process uses these streams to feed input to and getoutput from the subprocess. Because some native platforms onlyprovide limited buffer size for standard input and output streams,failure to promptly write the input stream or read the outputstream of the subprocess may cause the subprocess to block, andeven deadlock.

    The subprocess is not killed when there are no more references tothe Process object, but rather the subprocesscontinues executing asynchronously.

 

   There is no requirement that a process represented by aProcess object execute asynchronously or concurrentlywith respect to the Java process that owns the Processobject


原因在这里:

Process.exitValue() 采用非阻塞的方式返回,如果没有立即拿到返回值,则抛出异常

Process.waitFor() 当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。但是如果我们在调用此方法时,如果不注意的话,很容易出现主线程阻塞,Process也挂起的情况。在调用waitFor() 的时候,Process需要向主线程汇报运行状况,所以要注意清空缓存区,即InputStream和ErrorStream
解决方法:

p = Runtime.getRuntime().exec("staf  " + ipAddress + " process query handle " + handle);
            final InputStream is1 = p.getInputStream();   
            new Thread(new Runnable(){
                public void run() {
                    BufferedReader br = new BufferedReader(new InputStreamReader(is1));
                    try {
                       String outputLine = null;
                        while((outputLine=br.readLine())!= null) 
                             commandOutput.add(outputLine);
                        }catch (IOException e) {
                            e.printStackTrace();
                            }
                        }
                }).start();
                InputStream is2 = p.getErrorStream();   
                BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
                StringBuilder buf = new StringBuilder();
                String line = null;
                while((line = br2.readLine()) != null) buf.append(line);
                System.out.println("result:" + buf);
                while (br2.readLine() != null);
                try {
                    p.waitFor();
                    }catch (InterruptedException e){
                        e.printStackTrace();
                        }
                    queryExitValue=p.exitValue();
                    System.out.println( p.exitValue());

加入对输入和输出缓冲流的处理后这个问题顺利解决


原博客地址:

http://blog.csdn.net/carolzhang8406/article/details/7289309


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Java的Runtime类或ProcessBuilder类来执行cmd命令。例如,可以使用以下代码执行dir命令: ``` try { Process process = Runtime.getRuntime().exec("cmd /c dir"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } ``` 这将在控制台输出当前目录下的文件和文件夹列表。 ### 回答2: Java中可以使用`Runtime`类和`ProcessBuilder`类来执行cmd命令。 使用`Runtime`类执行cmd命令的步骤如下: 1. 创建一个`Runtime`对象:`Runtime rt = Runtime.getRuntime();` 2. 使用`rt.exec("cmd命令")`来执行cmd命令,例如:`rt.exec("cmd /c dir");` 3. 通过`Process`对象获取执行结果并处理,例如可以使用`BufferedReader`读取`Process.getInputStream()`获取cmd命令执行的结果。 使用`ProcessBuilder`类执行cmd命令的步骤如下: 1. 创建一个`ProcessBuilder`对象:`ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "cmd命令");` 2. 通过`ProcessBuilder`对象的`start()`方法启动cmd进程并执行命令:`Process process = pb.start();` 3. 通过`Process`对象获取执行结果并处理,例如可以使用`BufferedReader`读取`Process.getInputStream()`获取cmd命令执行的结果。 需要注意的是,执行cmd命令时可能有一些限制,例如命令执行路径的权限问题。另外,还需要注意处理cmd命令执行过程中可能出现的异常情况。 ### 回答3: Java可以通过使用ProcessBuilder类或Runtime类来执行cmd命令。 使用ProcessBuilder类执行cmd命令的步骤如下: 1. 创建ProcessBuilder对象,传入要执行cmd命令作为参数。 2. 调用ProcessBuilder对象的start()方法,启动进程并执行命令。 3. 使用ProcessBuilder对象的waitFor()方法,等待进程执行完成。 4. 使用ProcessBuilder对象的getInputStream()方法获取命令执行的输出。 示例代码如下: ``` ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir"); pb.redirectErrorStream(true); Process process = pb.start(); process.waitFor(); InputStream inputStream = process.getInputStream(); int ch; while ((ch = inputStream.read()) != -1) { System.out.print((char) ch); } ``` 上述代码中执行的是`dir`命令,通过循环读取InputStream的内容,可以获取到命令执行后返回的结果。 使用Runtime类执行cmd命令的步骤如下: 1. 调用Runtime类的getRuntime()方法获取Runtime对象。 2. 调用Runtime对象的exec()方法,传入要执行cmd命令作为参数,返回一个Process对象。 3. 使用Process对象的waitFor()方法,等待进程执行完成。 4. 使用Process对象的getInputStream()方法获取命令执行的输出。 示例代码如下: ``` Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("cmd /c dir"); process.waitFor(); InputStream inputStream = process.getInputStream(); int ch; while ((ch = inputStream.read()) != -1) { System.out.print((char) ch); } ``` 上述代码中执行的同样是`dir`命令,通过循环读取InputStream的内容,可以获取到命令执行后返回的结果。 以上就是使用Java执行cmd命令的简单示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值