Java调用外部程序命令时线程阻塞问题分析

2023-05-16

    文章参考http://www.qqread.com/java/2010/05/w493489.html

    今天要写个远程重启服务的功能,为了开发速度,暂时定为Java代码+WMIC命令的方法,简单的说,就是利用Java调用本机应用程序的方法。涉及到的 Java类有java.lang包里面的Runtime、Process、ProcessBuilder三个类,以及wmic中重启服务的命令。因为之前 也写过这方面的东西,所以很习惯性的写出了代码:

 

 

Process p = Runtime.getRuntime().exec("wmic ...");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String tmp = null;
while ((tmp = br.readline()) != null) {
  System.out.println(tmp);
}
int exitValue = p.waitfor();
 

 

  运行,结果发现程序不能退出,Debug发现程序阻塞在br.readline()中了,强制结束程序,发现重启服务的命令正常下下去了,去掉程序中获得标准输出的地方和获得返回结果的地方,命令也能正常下去,而且正常退出。

  为什么程序会阻塞呢?Google了一下,发现了大家的解释,应该也是比较权威的解释吧:每个进程都有自己的标准输入、标准输出、标准错误输出,对于某些 依赖于OS的进程,可能其输出缓冲区很小,如果不能及时的读出(标准输出、标注错误输出),将导致进程不能正常退出。我的程序中标准输出已经读了,显然原因不是这个,难道是错误输出缓冲区中的数据没有读出导致的?带着这个疑问,对程序作了一些更改:

 

ProcessBuilder pb = new ProcessBuilder("wmic",...);
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String tmp = null;
while ((tmp = br.readline()) != null) {
  System.out.println(tmp);
}
int exitValue = p.waitfor();
  

  编译运行,发现还是有问题,依然还是阻塞。又google了一下,大家的评论大多还是关于标准输出和标准错误输出,那这程序应该是没有问题了。后来在 cmd中敲入wmic的命令,发现wmic命令敲入以后会进入一个自有的提示符中,难道是因为标准输入的问题。后来又google了一下,验证了我的猜 想,果然是因为wmic进程会等待标准输入,而程序中没有处理标准输入的地方,是标准输入阻塞了进程的退出,修改代码:

 

ProcessBuilder pb = new ProcessBuilder("wmic",...);
pb.redirectErrorStream(true);
Process p = pb.start();
p.getOutputStream().close();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String tmp = null;
while ((tmp = br.readline()) != null) {
  System.out.println(tmp);
}
int exitValue = p.waitfor();
   编译运行,程序成功执行。果然是标准输入的原因。

  后来执行的过程中换了一个服务的名称,发现执行失败(能够正常退出,但是返回的结果是“无效动作”),但是同样的命令,在命令行中执行成功,而且直接适用 Runtime.exec()方法中写入整个命令也能够执行成功,难道是ProcessBuilder的错误,ProcessBuilder构造函数有两 个:

  ProcessBuilder(List<String> command)

  ProcessBuilder(String... command)

 

  找到ProcessBuilder的源代码,发现了对List<String>的解析方法:JDK将List中的所有字符串用空格连接,对 list中的每个字符串JDK先判断串中是否包含空格,如果包含空格,用双引号将该字符串引起来,再拼到前面字符串的后面(应该是为了解决路径中包含空格 的问题),可恰好Wmic命令的参数中有一段是name="ServiceName",如果ServiceName中包换空格,JDK就会把 name="service name"的外层加一个双引号,导致wmic不能解析该命令了。

  问题终于全都解决了,耗费了多半天的时间,不过收获总是有的,这里总结一下,在使用Java调用外部命令的时候,一定要注意对标准输出、标准输入和错误输 出的处理。对于一般的命令,只需要将标准输出和错误输出合并,一起读出来或者在另外的线程中读出来,而对于一些特殊的命令,还有处理标准输入。建议即使不 使用标准输入,先close了,总是不会出错了。另外,使用ProcessBuilder时要注意它的空格处理方式是否是你想要的,如果不是,就不能用 ProcessBuilder了,直接使用Runtime.exec()就好了。

    另外,如果子进程Process运行的工作目录与当前主线程的工作目录一相同,则可以用下面两种方法指定子进程Process运行的工作目录。

  ProcessBuilder.directory(new File("filepath"));

  Runtime.getRuntime().exec(command, evn, new File("filepath"));

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java调用外部程序命令时线程阻塞问题分析 的相关文章

  • 如何使用 FileChannel 将一个文件的内容附加到另一个文件的末尾?

    File a txt好像 ABC File d txt好像 DEF 我正在尝试将 DEF 附加到 ABC 所以a txt好像 ABC DEF 我尝试过的方法总是完全覆盖第一个条目 所以我总是最终得到 DEF 这是我尝试过的两种方法 File
  • 如何将 Java 赋值表达式转换为 Kotlin

    java中的一些东西就像 int a 1 b 2 c 1 if a b c System out print true 现在它应该转换为 kotlin 就像 var a Int 1 var b Int 2 var c Int 1 if a
  • JNI 不满意链接错误

    我想创建一个简单的 JNI 层 我使用Visual studio 2008创建了一个dll Win 32控制台应用程序项目类型 带有DLL作为选项 当我调用本机方法时 出现此异常 Exception occurred during even
  • 在数据流模板中调用 waitUntilFinish() 后可以运行代码吗?

    我有一个批处理 Apache Beam 作业 它从 GCS 获取文件作为输入 我的目标是根据执行后管道的状态将文件移动到两个 GCS 存储桶之一 如果管道执行成功 则将文件移动到存储桶 A 否则 如果管道在执行过程中出现任何未处理的异常 则
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • Java 页面爬行和解析之 Crawler4j 与 Jsoup

    我想获取页面的内容并提取其中的特定部分 据我所知 此类任务至少有两种解决方案 爬虫4j https github com yasserg crawler4j and Jsoup http jsoup org 它们都能够检索页面的内容并提取其
  • Prim 的迷宫生成算法:获取相邻单元格

    我基于 Prim 算法编写了一个迷宫生成器程序 该算法是 Prim 算法的随机版本 从充满墙壁的网格开始 选择一个单元格 将其标记为迷宫的一部分 将单元格的墙壁添加到墙壁列表中 While there are walls in the li
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 从 android 简单上传到 S3

    我在网上搜索了从 android 上传简单文件到 s3 的方法 但找不到任何有效的方法 我认为这是因为缺乏具体步骤 1 https mobile awsblog com post Tx1V588RKX5XPQB TransferManage
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • 归并排序中的递归:两次递归调用

    private void mergesort int low int high line 1 if low lt high line 2 int middle low high 2 line 3 mergesort low middle l
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • Android JNI C 简单追加函数

    我想制作一个简单的函数 返回两个字符串的值 基本上 java public native String getAppendedString String name c jstring Java com example hellojni He
  • Springs 元素“beans”不能具有字符 [children],因为该类型的内容类型是仅元素

    我在 stackoverflow 中搜索了一些页面来解决这个问题 确实遵循了一些正确的答案 但不起作用 我是春天的新人 对不起 这是我的调度程序 servlet
  • 将 JTextArea 内容写入文件

    我在 Java Swing 中有一个 JTextArea 和一个 提交 按钮 需要将textarea的内容写入一个带有换行符的文件中 我得到的输出是这样的 它被写为文件中的一个字符串 try BufferedWriter fileOut n
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe
  • 中断连接套接字

    我有一个 GUI 其中包含要连接的服务器列表 如果用户单击服务器 则会连接到该服务器 如果用户单击第二个服务器 它将断开第一个服务器的连接并连接到第二个服务器 每个新连接都在一个新线程中运行 以便程序可以执行其他任务 但是 如果用户在第一个
  • Jackson 将单个项目反序列化到列表中

    我正在尝试使用一项服务 该服务为我提供了一个带有数组字段的实体 id 23233 items name item 1 name item 2 但是 当数组包含单个项目时 将返回该项目本身 而不是包含一个元素的数组 id 43567 item
  • Swagger/Openapi-Annotations:如何使用 $ref 生成 allOf?

    我正在生成 Rest 端点 包括添加OpenAPI Swagger对生成的代码进行注释 虽然它对于基本类型运行得很好 但我在自定义类方面遇到了一些问题 现在我有很多自定义类的重复架构条目 使用 Schema 实现 MyClass class

随机推荐

  • 学习笔记—— unreferenced local variable

    file c xff08 xff09 warning C 39 xxx 39 unreferenced local variable 变量XXX定义了 但是在程序中没有使用到 发出的一则警告 目前来看 xff0c 不影响程序的运行
  • STM32定时器配置为编码器模式(转)

    文章目录 一 编码器原理 二 为什么要用编码器 三 STM32编码器配置相关 四 STM32实战代码 五 一些注意 参考 一 编码器原理 如果两个信号相位差为90度 xff0c 则这两个信号称为正交 由于两个信号相差90度 xff0c 因此
  • java实现倒计时

    package timer import java util Calendar import java util Date import java util Timer import java util TimerTask java演示倒计
  • linux终端字符串转字符画

    概述 xff1a 将字符串 xff08 非图像 xff09 转换成字符画 xff0c 效果如图 xff1a lt
  • fastboot -- 如何刷系统中各个img文件

    Android系统adb刷机 作者 xff1a 郑鹤翔 在android的各个可用软件中 xff0c adb fastboot是最常用的一种 xff0c 作为开发人员 xff0c 我们需要经常的进行内核 xff0c 系统代码等的修改 xff
  • AndroidStudio Kotlin项目搭建

    简介 xff1a 本文主要先大概介绍一下怎么在as上搭建kotlin项目 xff0c 然后主要具体介绍kotlin的语法 安装kotlin plugin 在AS 3 0及以后的版本是自带Kotlin plugin的 xff0c 但是如果你现
  • Mariadb安装之后的各种设置

    1 启动MariaDB 安装完成MariaDB xff0c 首先启动MariaDB xff0c 两条命令都可以 systemctl start mariadb 或者 service mariadb start 设置开机启动 systemct
  • python读取文件失败解决方案

    python读取文件失败解决方法 我的目录如下 python text files pi digits txt python text files file reader py 1 python默认读取当前根目录 注意 Linux 目录间用
  • from matplotlib.cbook import is_string_like, el ImportError: cannot import name 'is_string_like'

    Traceback most recent call last File 34 321 py 34 line 2 in lt module gt import matplotlib pyplot as pt File 34 C Progra
  • STM32F4XX 采集编码器的溢出处理

    STM32F4XX定时器16位 xff0c 采集编码器时候会在0xFFFF溢出 xff08 假设配置period 61 0xFFFF xff09 假设不溢出的情况下1ms之内编码器变化的最大范围小于0x7FFF xff0c 则关于溢出则可以
  • dependencyManagement和dependencies的区别

    dependencyManagement和dependencies的区别 参考 xff1a http zhaoshijie iteye com blog 2094478 pom xml中build标签 cpf2016的博客 CSDN博客 还
  • VScode播放网易云音乐(详细讲解)

    步骤 安装插件 xff1a VSC Netease Music 按shift 43 ctrl 43 p xff0c 输入 nete 出现下图 在按shift 43 ctrl 43 p xff0c 输入 nete 即可选择播放音乐 xff08
  • 安装和配置openssl

    Steps to download compile and install are as follows Note Replace 0 9 8e with your version number Downloading OpenSSL Ru
  • 自定义异常的使用

    下面是定义一个自定义异常的例子 xff0c 开发中可以以此作为参考 xff0c 根据项目需求编写自己的异常类 package com thinkgem wlw modules job service 自定义异常要继承 Exception 类
  • Ant中的classpath配置和使用

    Ant手册中配置classpath采用classpath标签 xff0c 可是我发现这样配置总是不好用 xff0c 还是直接用path设置classpath 一 xff09 设置classpath的方法 lt path id 61 34 p
  • 在运行jar包中正确读取资源文件

    可能有不少初学者会有这样的困惑 xff1a 在你的代码里调用了一些资源文件 xff0c 如图片 xff0c 音乐等 xff0c 在调试环境或单独运行的时候可以正常显示或播放 xff0c 而一旦打包到jar文件中 xff0c 这些东东就再也出
  • Ant发布war包时,任务卡住不动也不报错

    使用ant给项目发布环境时 xff0c 任务卡住不动也不报错 xff0c 在网上查询了些资料 xff0c 估计是ant执行任务时虚拟机内存不够用 针对这个问题 xff0c 可以通过以下两种方法解决 xff1a 1 xff09 在javac节
  • Oracle函数:sys_connect_by_path

    Oracle函数 sys connect by path 主要用于树查询 层次查询 以及 多列转行 其语法一般为 xff1a select sys connect by path column name 39 connect symbol
  • JVM(Java虚拟机)中进程工作目录讲解

    每次我们用Java命令运行我们的Java程序 xff0c 都会在JVM中开启一个进程 xff0c 对于每一个进程 xff0c 都会有一个相对应的工作目录 xff0c 这个工作目录在虚拟机初始化的时候就已经设置好了 xff0c 默认的情况下
  • Java调用外部程序命令时线程阻塞问题分析

    文章参考 http www qqread com java 2010 05 w493489 html 今天要写个远程重启服务的功能 xff0c 为了开发速度 xff0c 暂时定为Java代码 43 WMIC命令的方法 xff0c 简单的说