- 浏览: 8471 次
- 性别:
- 来自: 北京
最新评论
看到很多judge online软件均实现了c,c++,java等语言的在线编译,并且把执行结果返回到交互页面。分析了一下原理,现在说说我的实现思路。
1. 将用户写在表单中程序在服务器的用户特定目录生成相应的.java文件。
2. 利用Runtime.exec()方法执行javac,java等编译,执行方法并返回结果。
3. 通过Process.exitValue()方法和waitFor()方法获取单进程中 java文件执行后退出信息
4. 将程序执行结果获异常按原样返回给用户。
编译器的核心在于远程编译的实现,我们这里只讨论Runtime对象实现新进程中执行编译。
Runtime的使用
这个程序用exec调用了一个外部命令之后马上使用exitValue就对其返回值进行检查,让我们看看会出现什么问题。
import java.util.*;
import java.io.*;
import java.io.*;
public class BadExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
A run of BadExecJavac produces:
E:classescomjavaworldjpitfallsarticle2>java BadExecJavac
java.lang.IllegalThreadStateException: process has not exited
at java.lang.Win32Process.exitValue(Native Method)
at BadExecJavac.main(BadExecJavac.java:13)
这里看原文就可以了解,这里主要的问题就是错误的调用了exitValue来取得外部命令的返回值(呵呵,这个错误我也曾经犯过),因为exitValue这个方法是不阻塞的,程序在调用这个方法时外部命令并没有返回所以造成了异常的出现,这里是由另外的方法来等待外部命令执行完毕的,就是waitFor方法,这个方法会一直阻塞直到外部命令执行结束,然后返回外部命令执行的结果,作者在这里一顿批评设计者的思路有问题,呵呵,反正我是无所谓阿,能用就可以拉。但是作者在这里有一个说明,就是exitValue也是有好多用途的。因为当你在一个Process上调用waitFor方法时,当前线程是阻塞的,如果外部命令无法执行结束,那么你的线程就会一直阻塞下去,这种意外会影响我们程序的执行。所以在我们不能判断外部命令什么时候执行完毕而我们的程序还需要继续执行的情况下,我们就应该循环的使用exitValue来取得外部命令的返回状态,并在外部命令返回时作出相应的处理。
2、对exitValue处改进了的程序
import java.util.*;
import java.io.*;
import java.io.*;
public class BadExecJavac2
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
不幸的是,这个程序也无法执行完成,它没有输出但却一直悬在那里,这是为什么那?
JDK文档中对此有如此的解释:因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入和从标准输入快速的读入都有可能造成子进程的锁,甚至死锁。
文档引述完了,作者又开始批评了,他说JDK仅仅说明为什么问题会发生,却并没有说明这个问题怎么解决,这的确是个问题哈。紧接着作者说出自己的做法,就是在执行完外部命令后我们要控制好Process的所有输入和输出(视情况而定),在这个例子里边因为调用的是Javac,而他在没有参数的情况下会将提示信息输出到标准出错,所以在下面的程序中我们要对此进行处理。
import java.util.*;
import java.io.*;
public class MediocreExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
程序的运行结果为
E:classescomjavaworldjpitfallsarticle2>java MediocreExecJavac
Usage: javac
Usage: javac
where includes:
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-O Optimize; may hinder debugging or enlarge class files
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath Specify where to find user class files
-sourcepath Specify where to find input source files
-bootclasspath Override location of bootstrap class files
-extdirs Override location of installed extensions
-d Specify where to place generated class files
-encoding Specify character encoding used by source files
-target Generate class files for specific VM version
Process exitValue: 2
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-O Optimize; may hinder debugging or enlarge class files
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath Specify where to find user class files
-sourcepath Specify where to find input source files
-bootclasspath Override location of bootstrap class files
-extdirs Override location of installed extensions
-d Specify where to place generated class files
-encoding Specify character encoding used by source files
-target Generate class files for specific VM version
Process exitValue: 2
哎,不管怎么说还是出来了结果,作者作了一下总结,就是说,为了处理好外部命令大量输出的情况,你要确保你的程序处理好外部命令所需要的输入或者输出。
下一个题目,当我们调用一个我们认为是可执行程序的时候容易发生的错误(今天晚上我刚刚犯这个错误,没事做这个练习时候发生的)
import java.util.*;
import java.io.*;
import java.io.*;
public class BadExecWinDir
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("dir");
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("dir");
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
A run of BadExecWinDir produces:
E:classescomjavaworldjpitfallsarticle2>java BadExecWinDir
java.io.IOException: CreateProcess: dir error=2
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.(Unknown Source)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at BadExecWinDir.main(BadExecWinDir.java:12)
说实在的,这个错误还真是让我摸不着头脑,我觉得在windows中返回2应该是没有找到这个文件的缘故,可能windows 2000中只有cmd命令,dir命令不是当前环境变量能够解释的吧。我也不知道了,慢慢往下看吧。
E:classescomjavaworldjpitfallsarticle2>java GoodWindowsExec "dir *.java"
Execing cmd.exe /C dir *.java
OUTPUT> Volume in drive E has no label.
OUTPUT> Volume Serial Number is 5C5F-0CC9
OUTPUT>
OUTPUT> Directory of E:classescomjavaworldjpitfallsarticle2
OUTPUT>
OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java
OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java
OUTPUT>10/24/00 08:45p 488 BadExecJavac.java
OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java
OUTPUT>10/24/00 09:13p 930 BadExecWinDir.java
OUTPUT>10/22/00 09:21a 2,282 BadURLPost.java
OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java
... (some output omitted for brevity)
OUTPUT>10/12/00 09:29p 151 SuperFrame.java
OUTPUT>10/24/00 09:23p 1,814 TestExec.java
OUTPUT>10/09/00 05:47p 23,543 TestStringReplace.java
OUTPUT>10/12/00 08:55p 228 TopLevel.java
OUTPUT> 22 File(s) 46,661 bytes
OUTPUT> 19,678,420,992 bytes free
ExitValue: 0
最后的一个漏洞的地方就是错误的认为exec方法会接受所有你在命令行或者Shell中输入并接受的字符串。这些错误主要出现在命令作为参数的情况下,程序员错误的将所有命令行中可以输入的参数命令加入到exec中(这段翻译的不好,凑合看吧)。下面的例子中就是一个程序员想重定向一个命令的输出。
import java.util.*;
import java.io.*;
E:classescomjavaworldjpitfallsarticle2>java BadWinRedirect
OUTPUT>'Hello World' > test.txt
ExitValue: 0
import java.util.*;
import java.io.*;
E:classescomjavaworldjpitfallsarticle2>java GoodWinRedirect test.txt
OUTPUT>'Hello World'
ExitValue: 0
嘿,果然和作者想的一样,就是因为dir命令是由windows中的解释器解释的,直接执行dir时无法找到dir.exe这个命令,所以会出现文件未找到这个2的错误。如果我们要执行这样的命令,就要先根据操作系统的不同执行不同的解释程序command.com 或者cmd.exe。
作者对上边的程序进行了修改
import java.util.*;
import java.io.*;
import java.io.*;
class StreamGobbler extends Thread
{
InputStream is;
String type;
{
InputStream is;
String type;
StreamGobbler(InputStream is, String type)
{
this.is = is;
this.type = type;
}
{
this.is = is;
this.type = type;
}
public void run()
{
try
{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
{
try
{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public class GoodWindowsExec
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java GoodWindowsExec ");
System.exit(1);
}
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java GoodWindowsExec ");
System.exit(1);
}
try
{
String osName = System.getProperty("os.name" );
String[] cmd = new String[3];
{
String osName = System.getProperty("os.name" );
String[] cmd = new String[3];
if( osName.equals( "Windows NT" ) )
{
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
else if( osName.equals( "Windows 95" ) )
{
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
{
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
else if( osName.equals( "Windows 95" ) )
{
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0] + " " + cmd[1]
+ " " + cmd[2]);
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
System.out.println("Execing " + cmd[0] + " " + cmd[1]
+ " " + cmd[2]);
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
Running GoodWindowsExec with the dir command generates:
E:classescomjavaworldjpitfallsarticle2>java GoodWindowsExec "dir *.java"
Execing cmd.exe /C dir *.java
OUTPUT> Volume in drive E has no label.
OUTPUT> Volume Serial Number is 5C5F-0CC9
OUTPUT>
OUTPUT> Directory of E:classescomjavaworldjpitfallsarticle2
OUTPUT>
OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java
OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java
OUTPUT>10/24/00 08:45p 488 BadExecJavac.java
OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java
OUTPUT>10/24/00 09:13p 930 BadExecWinDir.java
OUTPUT>10/22/00 09:21a 2,282 BadURLPost.java
OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java
... (some output omitted for brevity)
OUTPUT>10/12/00 09:29p 151 SuperFrame.java
OUTPUT>10/24/00 09:23p 1,814 TestExec.java
OUTPUT>10/09/00 05:47p 23,543 TestStringReplace.java
OUTPUT>10/12/00 08:55p 228 TopLevel.java
OUTPUT> 22 File(s) 46,661 bytes
OUTPUT> 19,678,420,992 bytes free
ExitValue: 0
这里作者教了一个windows中很有用的方法,呵呵,至少我是不知道的,就是cmd.exe /C +一个windows中注册了后缀的文档名,windows会自动地调用相关的程序来打开这个文档,我试了一下,的确很好用,但是好像文件路径中有空格的话就有点问题,我加上引号也无法解决。
这里作者强调了一下,不要假设你执行的程序是可执行的程序,要清楚自己的程序是单独可执行的还是被解释的,本章的结束作者会介绍一个命令行工具来帮助我们分析。
这里还有一点,就是得到process的输出的方式是getInputStream,这是因为我们要从Java 程序的角度来看,外部程序的输出对于Java来说就是输入,反之亦然。
最后的一个漏洞的地方就是错误的认为exec方法会接受所有你在命令行或者Shell中输入并接受的字符串。这些错误主要出现在命令作为参数的情况下,程序员错误的将所有命令行中可以输入的参数命令加入到exec中(这段翻译的不好,凑合看吧)。下面的例子中就是一个程序员想重定向一个命令的输出。
import java.util.*;
import java.io.*;
// StreamGobbler omitted for brevity
public class BadWinRedirect
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World' > test.txt");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World' > test.txt");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
Running BadWinRedirect produces:
E:classescomjavaworldjpitfallsarticle2>java BadWinRedirect
OUTPUT>'Hello World' > test.txt
ExitValue: 0
程序员的本意是将Hello World这个输入重订向到一个文本文件中,但是这个文件并没有生成,jecho仅仅是将命令行中的参数输出到标准输出中,用户觉得可以像dos中重定向一样将输出重定向到一个文件中,但这并不能实现,用户错误的将exec认为是一个shell解释器,但它并不是,如果你想将一个程序的输出重定向到其他的程序中,你必须用程序来实现他。可用java.io中的包。
import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
InputStream is;
String type;
OutputStream os;
{
InputStream is;
String type;
OutputStream os;
StreamGobbler(InputStream is, String type)
{
this(is, type, null);
}
{
this(is, type, null);
}
StreamGobbler(InputStream is, String type, OutputStream redirect)
{
this.is = is;
this.type = type;
this.os = redirect;
}
{
this.is = is;
this.type = type;
this.os = redirect;
}
public void run()
{
try
{
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);
{
try
{
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
{
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
{
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public class GoodWinRedirect
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE java GoodWinRedirect ");
System.exit(1);
}
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE java GoodWinRedirect ");
System.exit(1);
}
try
{
FileOutputStream fos = new FileOutputStream(args[0]);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World'");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
{
FileOutputStream fos = new FileOutputStream(args[0]);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World'");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
// kick them off
errorGobbler.start();
outputGobbler.start();
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
Running GoodWinRedirect produces:
E:classescomjavaworldjpitfallsarticle2>java GoodWinRedirect test.txt
OUTPUT>'Hello World'
ExitValue: 0
这里就不多说了,看看就明白,紧接着作者给出了一个监测命令的小程序
import java.util.*;
import java.io.*;
import java.io.*;
// class StreamGobbler omitted for brevity
public class TestExec
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java TestExec "cmd"");
System.exit(1);
}
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java TestExec "cmd"");
System.exit(1);
}
try
{
String cmd = args[0];
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
{
String cmd = args[0];
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERR");
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERR");
// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUT");
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
对这个程序进行运行:
E:classescomjavaworldjpitfallsarticle2>java TestExec "e:javadocsindex.html"
java.io.IOException: CreateProcess: e:javadocsindex.html error=193
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.(Unknown Source)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at TestExec.main(TestExec.java:45)
E:classescomjavaworldjpitfallsarticle2>java TestExec "e:javadocsindex.html"
java.io.IOException: CreateProcess: e:javadocsindex.html error=193
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.(Unknown Source)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at TestExec.main(TestExec.java:45)
193在windows中是说这不是一个win32程序,这说明路径中找不到这个网页的关联程序,下面作者决定用一个绝对路径来试一下。
E:classescomjavaworldjpitfallsarticle2>java TestExec
"e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html"
ExitValue: 0
"e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html"
ExitValue: 0
好用了,这个我也试了一下,用的是IE。
最后,作者总结了几条规则,防止我们在进行Runtime.exec()调用时出现错误。
最后,作者总结了几条规则,防止我们在进行Runtime.exec()调用时出现错误。
在一个外部进程执行完之前你不能得到他的退出状态
在你的外部程序开始执行的时候你必须马上控制输入、输出、出错这些流。
你必须用Runtime.exec()去执行程序
你不能象命令行一样使用Runtime.exec()。
在nea需要动态来添加到RNC的路由,可以利用Runtime.exec方法来实现
具体实现如下:
其中的ip参数到时候可以是动态获取就可以了。
String[] cmds = {"cmd.exe","/c","route add 11.11.11.11 mask 255.255.255.255 11.11.11.1 metric 30 > tree.txt"};
try {
Process ps = Runtime.getRuntime().exec(cmds);
System.out.print(loadStream(ps.getInputStream()));
System.err.print(loadStream(ps.getErrorStream()));
} catch(IOException ioe) {
ioe.printStackTrace();
}
// read an input-stream into a String
static String loadStream(InputStream in) throws IOException {
int ptr = 0;
in = new BufferedInputStream(in);
StringBuffer buffer = new StringBuffer();
while( (ptr = in.read()) != -1 ) {
buffer.append((char)ptr);
}
return buffer.toString();
}
其中的 > tree.txt可以把执行这个指令的结果重新定向到一个文件里面,比如执行dir,tree等指令的时候。
如果要执行dos以外的指令,需要指定执行工作目录,
String[] cmds = {"cmd.exe","/c","radmin.exe"};
try {
Process ps = Runtime.getRuntime().exec(cmds,null,new File("C:\\Program Files\\Radmin"));
System.out.print(loadStream(ps.getInputStream()));
System.err.print(loadStream(ps.getErrorStream()));
} catch(IOException ioe) {
ioe.printStackTrace();
}
相关推荐
在本项目中,我们将探讨如何使用Java语言设计并实现一个编译器。编译器是计算机科学中的核心组件,它负责将源代码(通常是一种高级编程语言)转换为机器可执行的目标代码。以下是对实现这一过程涉及的关键知识点的...
- **Procyon**:另一个开源的反编译器,对Java 8的支持较好,同时可以处理Java字节码和Java源码。 3. **反编译过程**:反编译器首先解析.class文件中的字节码,然后根据JVM规范重建出类的结构,包括类名、方法、...
总的来说,Java反编译器是Java开发者不可或缺的工具之一,它们通过揭示字节码的内部工作,增强了代码的透明度和可理解性。"非常好用的Java反编译器"结合了易用性、效率和准确性,使得开发者可以更轻松地理解和修改已...
Java反编译器是开发人员在处理Java字节码时常用的一种工具,它能够将已编译的Java类文件(.class文件)转换回源代码形式,使得开发者可以查看和理解程序的内部工作原理,即使原始的源代码不再可用。在Java开发中,...
Java的字节码是平台无关的,它是由Java编译器从源代码(.java文件)编译得到的。在某些情况下,我们可能没有源代码但需要查看或修改执行的代码,这时反编译器就派上了用场。 标题中的"Java 反编译器V1.0(Java版)...
Java小型编译器是Java语言中的一种编译器,用于将Java源代码转换为机器代码或字节码。下面是Java小型编译器的知识点总结: 1. Lexical Analysis:词法分析是编译器的第一阶段,负责将源代码分解成单个词汇单元...
Java反编译器是一款用于查看Java字节码并将其转换回源代码的工具,它能够帮助开发者理解已编译的Java类文件的工作原理,尤其是在没有原始源代码的情况下。这款Java反编译器V1.0的绿色版无需安装,便于用户直接使用,...
标题提到的“一个很好用的JAVA反编译器”很可能指的是JD-GUI,一个流行且用户友好的Java反编译器。JD-GUI-0.3.1.windows是该软件的特定版本,专为Windows操作系统设计。 JD-GUI提供了直观的图形用户界面,允许...
Java反编译器是开发者和逆向工程人员用于查看Java字节码源代码的工具,因为Java程序在执行时是以类(class)文件的形式存在,这些文件是编译后的二进制格式,不直接包含原始的Java源代码。jdec(Java Decompiler)...
在线编译器是一种在网页上实现编程环境的工具,它允许开发者无需下载和安装特定的编程软件,即可在浏览器中编写、运行和测试代码。这种技术对于初学者、教育者和那些希望快速试验代码的开发者来说非常方便。本文将...
Java程序首先被Java编译器转化为字节码,这是一种平台无关的中间表示形式,存储在.class文件中。字节码由虚拟机(JVM)执行,提供了跨平台的运行能力。尽管字节码是低级的机器语言,但它并不直接对应于人类可读的源...
在提供的信息中,我们有一个名为"Java反编译器.exe"的可执行文件,这很可能是Java反编译器的用户界面版本。用户只需要将这个程序放在包含待反编译的.class文件的目录下,然后双击执行,就可以方便地进行反编译操作。...
标题中的“java 反编译器 反编译器”可能是指特定的反编译器软件或者是一个包含多个反编译器的集合。这可能是一个工具包,提供了多种反编译选项,以满足不同用户的需求。 描述中的“高效,反编译代码效果好”意味着...
Java编译器的主要任务包括语法分析、语义分析以及错误检查。 1. **语法分析**:编译器首先检查源代码的语法结构,确保符合Java语言的语法规则。例如,它会检查括号是否匹配、标识符是否合法、语句是否完整等。 2. ...
3. **JVM(Java虚拟机)**:Java编译器的产物是.class文件,它包含了JVM可执行的字节码。因此,理解JVM的工作原理、字节码格式以及JVM指令集是必要的。编译器需要能生成符合JVM规范的字节码。 4. **网络编程**:...
Java虚拟机即时编译器(JIT)是一种在运行时将Java字节码转换为本地机器码的技术,目的是提高程序执行效率。JIT编译器通常在程序启动后或运行时动态编译代码,这样可以利用运行时的信息进行优化,而静态编译则需要在...
Java反编译器是一种软件,它能够解析Java字节码(.class文件),并将其还原为类似原始Java源代码的形式。由于Java的编译过程是将源代码转化为字节码,这个过程是不可逆的,因此反编译得到的代码可能与原始源代码有所...
当编写Java程序时,源代码(.java文件)会被Java编译器(如javac)转换成字节码(.class文件),这是一种平台无关的中间表示。字节码可以在任何支持Java虚拟机(JVM)的平台上运行。 2. **反编译的概念**:反编译是...