java runtimeexec 的编写Word格式文档下载.docx
- 文档编号:20061961
- 上传时间:2023-01-16
- 格式:DOCX
- 页数:12
- 大小:20.98KB
java runtimeexec 的编写Word格式文档下载.docx
《java runtimeexec 的编写Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《java runtimeexec 的编写Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
首先说明一下,abort退出时JVM就是停止运行但并不一定进行shutdown。
这只有JVM在遇到SIGKILL信号或者windows中止进程的信号、本地方法发生类似于访问非法地址一类的内部错误时会出现。
这种情况下并不能保证shutdownhook是否被执行。
现在开始看这篇文章,呵呵。
首先讲的是Runtime.exec()方法的所有重载。
这里要注意的有一点,就是publicProcessexec(String[]cmdArray,String[]envp);
这个方法中cmdArray是一个执行的命令和参数的字符串数组,数组的第一个元素是要执行的命令往后依次都是命令的参数,envp我个人感觉应该和C中的execve中的环境变量是一样的,envp中使用的是name=value的方式。
<
!
--[if!
supportLists]-->
1、<
--[endif]-->
一个很糟糕的调用程序,代码如下,这个程序用exec调用了一个外部命令之后马上使用exitValue就对其返回值进行检查,让我们看看会出现什么问题。
importjava.util.*;
importjava.io.*;
publicclassBadExecJavac
{
publicstaticvoidmain(Stringargs[])
try
{
Runtimert=Runtime.getRuntime();
Processproc=rt.exec("
javac"
);
intexitVal=proc.exitValue();
System.out.println("
ProcessexitValue:
"
+exitVal);
}catch(Throwablet)
t.printStackTrace();
}
ArunofBadExecJavacproduces:
E:
classescomjavaworldjpitfallsarticle2>
javaBadExecJavac
java.lang.IllegalThreadStateException:
processhasnotexited
atjava.lang.Win32Process.exitValue(NativeMethod)
atBadExecJavac.main(BadExecJavac.java:
13)
这里看原文就可以了解,这里主要的问题就是错误的调用了exitValue来取得外部命令的返回值(呵呵,这个错误我也曾经犯过),因为exitValue这个方法是不阻塞的,程序在调用这个方法时外部命令并没有返回所以造成了异常的出现,这里是由另外的方法来等待外部命令执行完毕的,就是waitFor方法,这个方法会一直阻塞直到外部命令执行结束,然后返回外部命令执行的结果,作者在这里一顿批评设计者的思路有问题,呵呵,反正我是无所谓阿,能用就可以拉。
但是作者在这里有一个说明,就是exitValue也是有好多用途的。
因为当你在一个Process上调用waitFor方法时,当前线程是阻塞的,如果外部命令无法执行结束,那么你的线程就会一直阻塞下去,这种意外会影响我们程序的执行。
所以在我们不能判断外部命令什么时候执行完毕而我们的程序还需要继续执行的情况下,我们就应该循环的使用exitValue来取得外部命令的返回状态,并在外部命令返回时作出相应的处理。
2、对exitValue处改进了的程序
publicclassBadExecJavac2
intexitVal=proc.waitFor();
不幸的是,这个程序也无法执行完成,它没有输出但却一直悬在那里,这是为什么那?
JDK文档中对此有如此的解释:
因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入和从标准输入快速的读入都有可能造成子进程的锁,甚至死锁。
文档引述完了,作者又开始批评了,他说JDK仅仅说明为什么问题会发生,却并没有说明这个问题怎么解决,这的确是个问题哈。
紧接着作者说出自己的做法,就是在执行完外部命令后我们要控制好Process的所有输入和输出(视情况而定),在这个例子里边因为调用的是Javac,而他在没有参数的情况下会将提示信息输出到标准出错,所以在下面的程序中我们要对此进行处理。
publicclassMediocreExecJavac
InputStreamstderr=proc.getErrorStream();
InputStreamReaderisr=newInputStreamReader(stderr);
BufferedReaderbr=newBufferedReader(isr);
Stringline=null;
ERROR>
"
while((line=br.readLine())!
=null)
System.out.println(line);
/ERROR>
程序的运行结果为
javaMediocreExecJavac
Usage:
javac<
options>
<
sourcefiles>
where<
includes:
-gGeneratealldebugginginfo
-g:
noneGeneratenodebugginginfo
{lines,vars,source}Generateonlysomedebugginginfo
-OOptimize;
mayhinderdebuggingorenlargeclassfiles
-nowarnGeneratenowarnings
-verboseOutputmessagesaboutwhatthecompilerisdoing
-deprecationOutputsourcelocationswheredeprecatedAPIsareused
-classpath<
path>
Specifywheretofinduserclassfiles
-sourcepath<
Specifywheretofindinputsourcefiles
-bootclasspath<
Overridelocationofbootstrapclassfiles
-extdirs<
dirs>
Overridelocationofinstalledextensions
-d<
directory>
Specifywheretoplacegeneratedclassfiles
-encoding<
encoding>
Specifycharacterencodingusedbysourcefiles
-target<
release>
GenerateclassfilesforspecificVMversion
2
哎,不管怎么说还是出来了结果,作者作了一下总结,就是说,为了处理好外部命令大量输出的情况,你要确保你的程序处理好外部命令所需要的输入或者输出。
下一个题目,当我们调用一个我们认为是可执行程序的时候容易发生的错误(今天晚上我刚刚犯这个错误,没事做这个练习时候发生的)
publicclassBadExecWinDir
dir"
InputStreamstdin=proc.getInputStream();
InputStreamReaderisr=newInputStreamReader(stdin);
OUTPUT>
/OUTPUT>
ArunofBadExecWinDirproduces:
javaBadExecWinDir
java.io.IOException:
CreateProcess:
direrror=2
atjava.lang.Win32Process.create(NativeMethod)
atjava.lang.Win32Process.<
init>
(UnknownSource)
atjava.lang.Runtime.execInternal(NativeMethod)
atjava.lang.Runtime.exec(UnknownSource)
atBadExecWinDir.main(BadExecWinDir.java:
12)
说实在的,这个错误还真是让我摸不着头脑,我觉得在windows中返回2应该是没有找到这个文件的缘故,可能windows2000中只有cmd命令,dir命令不是当前环境变量能够解释的吧。
我也不知道了,慢慢往下看吧。
嘿,果然和作者想的一样,就是因为dir命令是由windows中的解释器解释的,直接执行dir时无法找到dir.exe这个命令,所以会出现文件未找到这个2的错误。
如果我们要执行这样的命令,就要先根据操作系统的不同执行不同的解释程序或者cmd.exe。
作者对上边的程序进行了修改
classStreamGobblerextendsThread
InputStreamis;
Stringtype;
StreamGobbler(InputStreamis,Stringtype)
this.is=is;
this.type=type;
publicvoidrun()
InputStreamReaderisr=newInputStreamReader(is);
Stringline=null;
System.out.println(type+"
>
+line);
}catch(IOExceptionioe)
ioe.printStackTrace();
publicclassGoodWindowsExec
if(args.length<
1)
USAGE:
javaGoodWindowsExec<
cmd>
System.exit
(1);
StringosName=System.getProperty("
os.name"
);
String[]cmd=newString[3];
if(osName.equals("
WindowsNT"
))
cmd[0]="
cmd.exe"
;
cmd[1]="
/C"
cmd[2]=args[0];
elseif(osName.equals("
Windows95"
Execing"
+cmd[0]+"
+cmd[1]
+"
+cmd[2]);
Processproc=rt.exec(cmd);
//anyerrormessage?
StreamGobblererrorGobbler=new
StreamGobbler(proc.getErrorStream(),"
ERROR"
//anyoutput?
StreamGobbleroutputGobbler=new
StreamGobbler(proc.getInputStream(),"
OUTPUT"
//kickthemoff
errorGobbler.start();
outputGobbler.start();
//anyerror?
?
ExitValue:
RunningGoodWindowsExecwiththedircommandgenerates:
javaGoodWindowsExec"
dir*.java"
Execingcmd.exe/Cdir*.java
VolumeindriveEhasnolabel.
VolumeSerialNumberis5C5F-0CC9
DirectoryofE:
classescomjavaworldjpitfallsarticle2
10/23/0009:
01p805BadExecBrowser.java
10/22/0009:
35a770BadExecBrowser1.java
10/24/0008:
45p488BadExecJavac.java
46p519BadExecJavac2.java
10/24/0009:
13p930BadExecWinDir.java
21a2,282BadURLPost.java
20a2,273BadURLPost1.java
...(someoutputomittedforbrevity)
10/12/0009:
29p151SuperFrame.java
23p1,814TestExec.java
10/09/0005:
47p23,543TestStringReplace.java
10/12/0008:
55p228TopLevel.java
22File(s)46,661bytes
19,678,420,992bytesfree
0
这里作者教了一个windows中很有用的方法,呵呵,至少我是不知道的,就是cmd.exe/C+一个windows中注册了后缀的文档名,windows会自动地调用相关的程序来打开这个文档,我试了一下,的确很好用,但是好像文件路径中有空格的话就有点问题,我加上引号也无法解决。
这里作者强调了一下,不要假设你执行的程序是可执行的程序,要清楚自己的程序是单独可执行的还是被解释的,本章的结束作者会介绍一个命令行工具来帮助我们分析。
这里还有一点,就是得到process的输出的方式是getInputStream,这是因为我们要从Java程序的角度来看,外部程序的输出对于Java来说就是输入,反之亦然。
最后的一个漏洞的地方就是错误的认为exec方法会接受所有你在命令行或者Shell中输入并接受的字符串。
这些错误主要出现在命令作为参数的情况下,程序员错误的将所有命令行中可以输入的参数命令加入到exec中(这段翻译的不好,凑合看吧)。
下面的例子中就是一个程序员想重定向一个命令的输出。
//StreamGobbleromittedforbrevity
publicclassBadWinRedirect
javajecho'
HelloWorld'
>
test.txt"
}catch(T
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java runtimeexec 的编写 编写