动态运行Java代码与进程。
动态运行Java代码与进程。
我创建了一个类,动态编译并加载到CustomClassLoader中,通过调用其main
方法在内存中执行一个没有类文件的Java源代码。\n尽管在我当前的代码中无法做到这一点(编译器API +类加载器+反射),但我需要捕获StdOut
,StdIn
和StdErr
。\n我的要求可能与这个问题中描述的相同,并且根据被接受的答案建议,使用java.lang.Process。如果我在文件系统中有物理文件可用,那么这将更容易,但在这种情况下我没有。\n我计划删除Classloader + Reflection
策略,改用建议;然而,我对使用Process类实际重定向Std*
并不熟悉。\n我应该如何在Java 7中做到这一点?(非常感谢代码片段)或者更重要的是,是否有更好的方法?
动态运行Java代码并使用Process解决方案
在Java中,你可以提供自己的PrintStream来覆盖stdout和stderr,以及一个InputStream来覆盖stdin。
个人而言,我不喜欢简单地丢弃原始流,因为我倾向于只想重定向或解析它,而不是停止它(尽管你也可以这样做)。
下面是一个简单的示例...
import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; public class RedirectStdOut { public static void main(String[] args) { Consumer stdConsumer = new Consumer() { public void processLine(StreamCapturer capturer, String text) { } public void processCharacter(StreamCapturer capturer, char character) { capturer.getParent().print(character); } }; StreamCapturer stdout = new StreamCapturer(stdConsumer, System.out); StreamCapturer stderr = new StreamCapturer(stdConsumer, System.err); System.setOut(new PrintStream(stdout)); System.setErr(new PrintStream(stderr)); System.out.println("This is a test"); System.err.println("This is an err"); } public static interface Consumer { public void processLine(StreamCapturer capturer, String text); public void processCharacter(StreamCapturer capturer, char character); } public static class StreamCapturer extends OutputStream { private StringBuilder buffer; private Consumer consumer; private PrintStream parent; private boolean echo = false; public StreamCapturer(Consumer consumer, PrintStream parent) { buffer = new StringBuilder(128); this.parent = parent; this.consumer = consumer; } public PrintStream getParent() { return parent; } public boolean shouldEcho() { return echo; } public void setEcho(boolean echo) { this.echo = echo; } public void write(int b) throws IOException { char c = (char) b; String value = Character.toString(c); buffer.append(value); if (value.equals("\n")) { consumer.processLine(this, value); buffer.delete(0, buffer.length()); } consumer.processCharacter(this, c); if (shouldEcho()) { parent.print(c); } } } }
现在,StreamCapturer有了如果需要可以回显输出的功能,我已将其关闭以演示使用Consumer的用法。根据你的需求,我通常使用Consumer来处理流中的内容,你可以等待完整的行或处理单个字符...
嗯,我明白你的想法。然而,使用这个解决方案,我需要"监视"的类始终实现一个类似processLine的方法,对吗?在我的情况下,我无法控制要执行的代码,所以似乎无法使用这个解决方案。你有什么想法吗?
如果你要运行的类将输出写入stdout,那么你可以使用这个概念来捕获该类正在写入的内容,并根据需要进行处理。
动态运行Java代码是一项常见的需求,但是在实现过程中可能会遇到一些问题。其中一个问题是如何在运行Java代码的同时捕捉输出结果。为了解决这个问题,可以使用Process类来动态运行Java代码,并且通过重定向System.out来捕捉输出。
具体的解决方法如下:
1. 首先,需要备份现有的输出流。这可以通过创建一个PrintStream对象并将其设置为System.out来实现。
PrintStream realSystemOut = System.out;
2. 接下来,将输出流重定向到其他流,例如FileOutputStream或其他流。
PrintStream overridePrintStream = new PrintStream(new FileOutputStream("log.txt")); System.setOut(overridePrintStream);
3. 然后,可以使用Process类来运行Java代码。
// 运行Java代码的命令 String command = "java MyClass"; Process process = Runtime.getRuntime().exec(command); // 等待进程结束 int exitValue = process.waitFor(); // 处理进程的输出 // ... // 将实际流恢复为System.out System.setOut(realSystemOut);
通过以上步骤,可以在运行Java代码的同时捕捉输出结果。在执行完Java代码后,记得将实际的输出流恢复为System.out。
希望以上方法对你有帮助。