- 浏览: 23897 次
- 性别:
- 来自: 北京
最新评论
2,如果调用外部java服务,如何在销毁进程的同时关闭它开启的外部服务?
3,如何获得执行进程的PID?
1,如何执行,如何用ProcessBuilder来简化操作
在ProcessBuilder(http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ProcessBuilder.html)有个简单的例子。
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); Map<String, String> env = pb.environment(); env.put("VAR1", "myValue"); env.remove("OTHERVAR"); env.put("VAR2", env.get("VAR1") + "suffix"); pb.directory("myDir"); Process p = pb.start();
这个例子描述了如何执行一个命令,但是如果你想从命令行读取输入输出呢?
假设我们想执行如下命令
Ipconfig –all
我们可以做如下改进
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ProcessExec {
private Process process;
public void execute()
throws InterruptedException, IOException {
List<String> command = new ArrayList<String>();
command.add( "cmd.exe" );
command.add( "/c" );
command.add( "ipconfig -all" );
// 执行命令
ProcessBuilder pb = new ProcessBuilder( ( command ) );
process = pb.start();
// 异步读取输出
InputStream inputStream = process.getInputStream();
InputStream errorStream = process.getErrorStream();
ExecutorService service = Executors.newFixedThreadPool( 2 );
ResultStreamHandler inputStreamHandler = new ResultStreamHandler( inputStream );
ResultStreamHandler errorStreamHandler = new ResultStreamHandler( errorStream );
service.execute( inputStreamHandler );
service.execute( errorStreamHandler );
process.waitFor();
service.shutdownNow();
}
class ResultStreamHandler
implements Runnable {
private InputStream inputStream;
ResultStreamHandler( InputStream inputStream ) {
this.inputStream = inputStream;
}
public void run() {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader( new InputStreamReader( inputStream ) );
String line = null;
while ( ( line = bufferedReader.readLine() ) != null ) {
System.out.println( line );
}
}
catch ( Throwable t ) {
}
finally {
try {
bufferedReader.close();
}
catch ( IOException e ) {
}
}
}
}
}
现在我们可以异步读取输出了,但其方式比较单一,我们可不可以直接输出到一个指定文件呢?
自jdk1.7起,ProcessBuilder增加Redirect来方便我们处理这个问题
1,输出有output, error两个流,输入有input流,相应的在这我们要创建3个文件
File errors = new File("C:/error.log");
File input = new File("C:/input.txt");
2创建input.txt文件,输入一下命令
Ipconfig –all
确定all后面有回车符
3 创建一个ProcessBuilder实例,指定“cmd”作为参数,表示我们想执行一个window命令
4 Redirect
输入输出流到不同的文件
pb.redirectError(errors);
pb.redirectOutput(output);
5 最后,执行命令
需要注意的是start必须在redirct设定后才调用
ProcessBuilder还有一些使用的方法
比如ProcessBuilder.Redirect.appendTo
这样每次输出到指定文件都追加到后面而不是覆盖
比较有用的还有inheritIO(), 调用这个方法可以redirect被执行命令的输入输出流到当前java进程的输入输出流,也就是说,如果你用eclipse执行,你在console里就可以看到输入输出。
2,如果调用外部java服务,如何在销毁进程的同时关闭它开启的外部服务?
有时候或许我们会执行一个外部的java应用
如:java –jar D:\\test.jar
假设test.jar 一旦启动会一直运行,那么问题来了,当process被销毁时,如何关闭这个外部进程呢?
有个bug专门描述了这个问题
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4770092
可以看出没有什么好的解决办法
但有时我们就想用这个功能,怎么办?
或许我们可以使用jdk自带的tools.jar
这个程序遍历虚拟机上所有的java程序,提取他们main class名,如果和指定的main class名匹配,则返回pid值
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
public class GetOwnPid {
public static void main(String[] args) {
new GetOwnPid().run();
}
public void run() {
System.out.println(getPid(this.getClass()));
}
public Integer getPid(Class<?> mainClass) {
MonitoredHost monitoredHost;
Set<Integer> activeVmPids;
try {
monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
activeVmPids = monitoredHost.activeVms();
MonitoredVm mvm = null;
for (Integer vmPid : activeVmPids) {
try {
mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
String mvmMainClass = MonitoredVmUtil.mainClass(mvm, true);
if (mainClass.getName().equals(mvmMainClass)) {
return vmPid;
}
} finally {
if (mvm != null) {
mvm.detach();
}
}
}
} catch (java.net.URISyntaxException e) {
throw new InternalError(e.getMessage());
} catch (MonitorException e) {
throw new InternalError(e.getMessage());
}
return null;
}
}
3, 如何获得执行进程的PID?
如果process因为未知的原因阻塞了,我们想直接kill它,如何获得该进程的pid呢?
在Unix,我们可以用反射,因为UnixProcess类有pid属性
/* 获取pid */
try {
Field f = process.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getInt(p);
} catch (Throwable e) {
}
}
在这里我们可以利用它的handle属性
首先下载jna.jar
process.getClass().getName().equals("java.lang.ProcessImpl")) {
/* determine the pid on windows plattforms */
try {
Field f = p.getClass().getDeclaredField("handle");
f.setAccessible(true);
long handl = f.getLong(p);
Kernel32 kernel = Kernel32.INSTANCE;
W32API.HANDLE handle = new W32API.HANDLE();
handle.setPointer(Pointer.createConstant(handl));
pid = kernel.GetProcessId(handle);
} catch (Throwable e) {
}
}
/* https://jna.dev.java.net/ */
public interface Kernel32 extends W32API {
Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class, DEFAULT_OPTIONS);
/* http://msdn.microsoft.com/en-us/library/ms683179(VS.85).aspx */
HANDLE GetCurrentProcess();
/* http://msdn.microsoft.com/en-us/library/ms683215.aspx */
int GetProcessId(HANDLE Process);
}
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.FromNativeContext;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIFunctionMapper;
import com.sun.jna.win32.W32APITypeMapper;
/** Base type for most W32 API libraries. Provides standard options
* for unicode/ASCII mappings. Set the system property w32.ascii
* to true to default to the ASCII mappings.
*/
public interface W32API extends StdCallLibrary, W32Errors {
/** Standard options to use the unicode version of a w32 API. */
Map UNICODE_OPTIONS = new HashMap() {
{
put(OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
}
};
/** Standard options to use the ASCII/MBCS version of a w32 API. */
Map ASCII_OPTIONS = new HashMap() {
{
put(OPTION_TYPE_MAPPER, W32APITypeMapper.ASCII);
put(OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.ASCII);
}
};
Map DEFAULT_OPTIONS = Boolean.getBoolean("w32.ascii") ? ASCII_OPTIONS : UNICODE_OPTIONS;
public class HANDLE extends PointerType {
@Override
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
/** Constant value representing an invalid HANDLE. */
HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{ super.setPointer(Pointer.createConstant(-1)); }
@Override
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
}
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
public interface W32Errors {
int NO_ERROR = 0;
int ERROR_INVALID_FUNCTION = 1;
int ERROR_FILE_NOT_FOUND = 2;
int ERROR_PATH_NOT_FOUND = 3;
}
String processName = rtb.getName();
Integer pid = tryPattern1(processName);
private static Integer tryPattern1(String processName) {
Integer result = null;
/* tested on: */
/* - windows xp sp 2, java 1.5.0_13 */
/* - mac os x 10.4.10, java 1.5.0 */
/* - debian linux, java 1.5.0_13 */
/* all return pid@host, e.g 2204@antonius */
Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(processName);
if (matcher.matches()) {
result = new Integer(Integer.parseInt(matcher.group(1)));
}
return result;
}
相关信息还可以参照http://bugs.sun.com/view_bug.do?bug_id=4244896
发表评论
-
ExecutorService - 10 tips and tricks(转)
2014-12-25 10:40 703ExecutorService abstraction h ... -
用bat脚本批量删除文件名中的特殊字符(空格,下划线...)
2014-05-16 11:00 7743把文件名中的'.'替换成'_' 并且去掉含有的空格 @echo ... -
由于夏令时而引起的DateFormat转换相差1小时的问题
2013-10-10 15:01 1693两个timezone对象,把第二个timez ... -
wicket 如何 加载 javascript 到 body
2013-06-10 11:21 687OnLoadHeaderItem 加载的js 在整个页面被加载 ... -
如何阻止在DropDown 菜单选项上click后,菜单消失及如何让input只接受数字输入
2013-06-10 11:10 3862百说不如一例 <!DOCTYPE html> &l ... -
用css消除button,selcet等控件选中时的虚线框
2013-03-19 08:44 1097调查了很多资料,只有下面的这一种适合我 input,butto ... -
Spring配置之context:property-placeholder
2013-02-27 23:12 0关于context:property-placeholder的 ...
相关推荐
在执行命令后,需要通过`Process`对象的`waitFor()`方法等待命令执行完成,获取退出状态码。 ```java int exitCode = process.waitFor(); System.out.println("Command exited with code: " + exitCode); ``` 退出...
Runtime类是每个Java应用程序都有的一个实例,它提供了执行系统命令的方法。我们可以通过getRuntime()方法获取到Runtime实例,然后调用exec()方法执行命令。例如,以下代码展示了如何使用Runtime类执行"mkdir"命令...
在Java编程环境中,有时我们...不过,根据标题和描述,这个文件很可能包含了一个示例,演示了如何在Java中使用`ProcessBuilder`执行Windows系统命令。如果你能提供代码内容,我可以进一步解释和扩展相关的编程知识点。
Java调用doc命令主要涉及到的是Java的进程操作和命令行接口。在Windows操作系统中,`.doc`文件通常是由Microsoft Word创建的文档。然而,“doc命令”可能是...正确理解和使用这些技术能够帮助你构建更强大的Java应用。
在上述代码中,我们使用了`Runtime.getRuntime().exec()`方法执行了"dir"命令,这是在Windows环境下列出当前目录下所有文件和目录的命令。然后,我们通过`BufferedReader`读取命令执行的输出并打印到控制台。 但是...
在Android应用开发中,执行命令行操作通常是通过Java的Runtime类或者使用第三方库如Apache Commons Exec来实现的。本文将详细讲解如何在Android应用中执行`cd`(改变目录)命令,以及相关的重要知识点。 首先,`cd`...
总的来说,通过分析和理解Android系统的进程模型,结合Java代码执行shell命令和解析输出,我们可以获取到当前栈顶应用的包名。这对于监控应用使用情况、优化性能或实现特定功能(如后台限制)非常有用。开发者在实际...
在这个场景中,我们讨论的是如何通过Java程序调用Python命令来执行DataX任务,实现从MySQL到ODPS的数据同步。 首先,我们需要理解Java与Python交互的基本原理。Java可以通过`Runtime.exec()`或`ProcessBuilder`类来...
总结来说,Java中的`Process`和`ProcessBuilder`是实现与操作系统交互的关键工具,允许开发者执行外部命令、传递参数、读写进程I/O,以及管理进程的生命周期。熟练掌握这些功能,可以帮助开发者编写更强大的跨平台...
Java操作DOS命令主要指的是通过Java程序调用操作系统(如Windows、Linux等)的命令行接口,执行系统级别的操作。这种技术在很多场景下都非常实用,例如自动...因此,在实际应用中,确保命令的正确性和安全性至关重要。
本教程将深入讲解如何在Android应用中通过Java代码执行shell命令,以提升应用的功能和效率。 一、Android与Shell命令 Android系统基于Linux内核,因此支持使用Linux命令行工具,即shell命令。这些命令提供了对系统...
在Java中调用这些命令时,只需将相应的命令替换到上述的`exec()`或`ProcessBuilder`中即可。 **注意安全**: 当调用CMD命令时,要特别小心,避免命令注入攻击。永远不要从不可信的来源接收命令字符串。如果需要动态...
ProcessBuilder类提供更灵活的方式来执行命令,它可以处理更复杂的命令行参数,包括环境变量和工作目录的设置。下面的例子展示了如何使用ProcessBuilder: ```java ProcessBuilder pb = new ProcessBuilder("cmd...
当需要在Android应用程序中执行shell命令时,我们可以利用Java的Runtime类或者ProcessBuilder类来实现。例如,可以创建一个Process对象来执行shell命令: ```java try { Process process = Runtime.getRuntime()....
在SpringBoot项目中,我们可以创建一个服务或者控制器,通过Java的Runtime类或者ProcessBuilder类来执行系统命令,即ADB命令。例如,以下是一个简单的示例,展示如何通过Java代码执行ADB命令: ```java import java...
- 在Java应用中,这种方式可以利用Linux的强大功能,比如处理文件系统、网络通信、系统服务等。 总的来说,Java执行Linux SH文件是一种常见的跨平台编程需求,它结合了Java的编程能力与Linux系统的强大功能,广泛...
`Runtime.exec()`方法用于执行命令,而`ProcessBuilder`提供了更灵活的方式来构建和执行命令。下面是一个简单的例子,演示如何执行一个shell脚本: ```java public class Main { public static void main(String[]...
"java中调用控制台程序"这个主题就是关于如何在Java应用程序中调用控制台命令,比如Windows系统的CMD命令行或者在Linux环境中使用wget工具。在Java中,我们可以使用Runtime类或者ProcessBuilder类来实现这样的功能。...
在Windows系统下,我们可能需要使用`cmd /c`来执行命令,例如`Runtime.getRuntime().exec("cmd /c dir")`。 然而,`Runtime.exec()`方法有一些限制,比如无法方便地处理错误输出流(stderr)和输入流。这时,`...
在Java中,我们可以使用`Runtime.getRuntime().exec()`方法或者`ProcessBuilder`类来执行系统命令。下面我们将详细介绍如何使用这两种方法实现“ping”命令。 ### 使用`Runtime.getRuntime().exec()`方法 1. **...