用Runtime.getRuntime().exec()需要注意的地方

有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序。

此方法返回一个java.lang.Process对象,该对象可以得到之前开启的进程的运行结果,还可以操作进程的输入输出流。

Process对象有以下几个方法:

  1、destroy()      杀死这个子进程

  2、exitValue()      得到进程运行结束后的返回状态

  3、waitFor()       得到进程运行结束后的返回状态,如果进程未运行完毕则等待知道执行完毕

  4、getInputStream()  得到进程的标准输出信息流

  5、getErrorStream()  得到进程的错误输出信息流

  6、getOutputStream() 得到进程的输入流

 

现在来讲讲exitValue(),当线程没有执行完毕时调用此方法会跑出IllegalThreadStateException异常,最直接的解决方法就是用waitFor()方法代替。

但是waitFor()方法也有很明显的弊端,因为java程序给进程的输出流分配的缓冲区是很小的,有时候当进程输出信息很大的时候回导致缓冲区被填满,如果不及时处理程序会阻塞。如果程序没有对进程的输出流处理的会就会导致执行exec()的线程永远阻塞,进程也不会执行下去直到输出流被处理或者java程序结束。

解决的方法就是处理缓冲区中的信息,开两个线程分别去处理标准输出流和错误输出流。

程序如下:

复制代码
复制代码
public class ExecTest {
    
    public static void main(String[] args) throws IOException, InterruptedException {
      String cmd = "cmd /c dir c:\\windows";
      final Process process = Runtime.getRuntime().exec(cmd);
      printMessage(process.getInputStream());
      printMessage(process.getErrorStream());
      int value = process.waitFor();
      System.out.println(value);
    }
    
    private static void printMessage(final InputStream input) {
      new Thread(new Runnable() {
         public void run() {
            Reader reader = new InputStreamReader(input);
            BufferedReader bf = new BufferedReader(reader);
            String line = null;
             try {
                while((line=bf.readLine())!=null) {
                    System.out.println(line);
                }
             } catch (IOException e) {
                e.printStackTrace();
             }
         }
      }).start();
    }
}
复制代码
复制代码

如上程序,读取进程的输出信息并打印到控制台就不会发生阻塞,程序能正常的结束。

 

tips:

  cmd命令不能需要加上cmd /c才能执行,不然java会去path中找dir.exe

  在windows一般字符集编码为GBK,需要在转换成Reader的时候指定为GBK编码.

### Java 中通过 `Runtime.getRuntime().exec()` 执行 ADB 命令 在 Java 程序中,`Runtime.getRuntime().exec()` 方法可以用来调用外部命令或脚本。对于 Android 开发者来说,ADB(Android Debug Bridge)是一个常用的工具,可以通过该方法来执行各种设备管理操作。 以下是关于如何使用 `Runtime.getRuntime().exec()` 来运行 ADB 命令的具体实现以及一些常见的注意事项: #### 实现示例 下面展示了一个简单的例子,说明如何通过 Java 调用 ADB 命令并获取其输出结果: ```java import java.io.BufferedReader; import java.io.InputStreamReader; public class AdbCommandExecutor { public static void main(String[] args) { try { // 定义要执行的 ADB 命令 String command = "adb devices"; // 使用 Runtime.getRuntime().exec() 运行命令 Process process = Runtime.getRuntime().exec(command); // 获取命令的标准输出流 BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()) ); StringBuilder outputBuilder = new StringBuilder(); String line; // 读取每一行输出直到结束 while ((line = reader.readLine()) != null) { outputBuilder.append(line).append("\n"); } // 输出最终的结果 System.out.println(outputBuilder.toString()); // 关闭资源 reader.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 上述代码展示了如何通过 `Runtime.getRuntime().exec()` 发起一个 ADB 请求,并捕获返回的数据[^1]。 #### 注意事项 1. **路径配置**: 如果程序无法找到 adb 可执行文件,则可能是因为环境变量 PATH 没有正确设置。在这种情况下,应该提供完整的绝对路径给 `adb` 文件所在位置[^2]。 修改后的命令如下所示: ```java String command = "/path/to/adb devices"; ``` 2. **权限问题**: 当尝试访问某些敏感功能时,可能会遇到权限足的情况。此时需要确保正在使用的账户具有足够的权限或者切换到超级用户模式下重新启动应用实例[^3]。 3. **异步处理**: 对于长时间运行的任务建议采用更高级别的 API 如 `ProcessBuilder`, 并考虑线程安全性和错误恢复机制的设计。 4. **异常捕捉**: 总是记得加入全面的异常处理器以应对潜在失败情形下的调试需求。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值