动态运行Java代码与进程。

14 浏览
0 Comments

动态运行Java代码与进程。

我创建了一个类,动态编译并加载到CustomClassLoader中,通过调用其main方法在内存中执行一个没有类文件的Java源代码。\n尽管在我当前的代码中无法做到这一点(编译器API +类加载器+反射),但我需要捕获StdOutStdInStdErr。\n我的要求可能与这个问题中描述的相同,并且根据被接受的答案建议,使用java.lang.Process。如果我在文件系统中有物理文件可用,那么这将更容易,但在这种情况下我没有。\n我计划删除Classloader + Reflection策略,改用建议;然而,我对使用Process类实际重定向Std*并不熟悉。\n我应该如何在Java 7中做到这一点?(非常感谢代码片段)或者更重要的是,是否有更好的方法?

0
0 Comments

动态运行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,那么你可以使用这个概念来捕获该类正在写入的内容,并根据需要进行处理。

0
0 Comments

动态运行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。

希望以上方法对你有帮助。

0