如何从java代码本身运行编译后的代码(
.class
)java?
我正在做一种提供服务,比如在服务器端编译和运行java代码并将输出提供给最终用户。
任何人都可以建议一种可以实现此目的的方法吗?
import java.io.*;
public class demo {
public static void main(String args[]) throws IOException, InterruptedException {
int result;
try {
System.out.println("command output:");
Process proc = Runtime.getRuntime().exec("java -cp . demoh");
InputStream in = proc.getInputStream();
result = proc.waitFor();
BufferedInputStream buffer = new BufferedInputStream(proc.getInputStream());
BufferedReader commandOutput = new BufferedReader(new InputStreamReader(buffer));
System.out.print(commandOutput);
String line = null;
try {
while ((line = commandOutput.readLine()) != null) {
System.out.print(line);
System.out.println("command output: " + line);
}//end while
commandOutput.close();
} catch (IOException e) {
//log and/or handle it
}
} catch (IOException e) {
System.err.println("IOException raised: " + e.getMessage());
}
}
}
如果磁盘上有
.class
文件,只需生成一个新进程并像从命令行一样运行 java 命令即可:
Process p = Runtime.getRuntime().exec("java <java class file>");
经过一些测试,以下代码对我有用:
public static void main(String args[]) throws IOException, InterruptedException {
int result;
try {
System.out.println("command output:");
Process proc = Runtime.getRuntime().exec("java -cp . Test");
InputStream errin = proc.getErrorStream();
InputStream in = proc.getInputStream();
BufferedReader errorOutput = new BufferedReader(new InputStreamReader(errin));
BufferedReader output = new BufferedReader(new InputStreamReader(in));
String line1 = null;
String line2 = null;
try {
while ((line1 = errorOutput.readLine()) != null ||
(line2 = output.readLine()) != null) {
if(line1 != null) System.out.print(line1);
if(line2 != null) System.out.print(line2);
}//end while
errorOutput.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}//end catc
result = proc.waitFor();
} catch (IOException e) {
System.err.println("IOException raised: " + e.getMessage());
}
}
这里请注意两件事:
Process process = Runtime.getRuntime().exec("java " + filePath); // without .class
Scanner output = new Scanner(process.getInputStream());
while (output.hasNext) {
String token = output.next();
...
}
此方法。
如需更多地控制 Java 编译器,请阅读 javax.tools 包。
package sourcerunner;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class SourceRunner {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, InterruptedException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(System.in, System.out, System.err, "src/sourcerunner/HelloWorld.java");
TimeUnit.SECONDS.sleep(1L);
Class<?> cls = Class.forName("sourcerunner.HelloWorld");
Object instance = cls.newInstance();
System.out.println(instance);
}
}
这是 HelloWorld 类:
package sourcerunner;
public class HelloWorld {
@Override
public String toString() {
return "Hello Java Compiler World.";
}
}
上面的代码非常不安全。一旦理解了代码,就可以修改它以使用新的 ClassLoader 来加载并实例化该类。确保类加载器具有最小权限。