从java代码运行.class文件

时间:2012-04-20 16:05:37

标签: java compiler-construction jvm

如何从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());
        }
    }
}

6 个答案:

答案 0 :(得分:1)

如果你在磁盘上的某个地方有.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());
    }
}

请注意以下两点:

  1. java进程给出的运行时错误被发送到错误流,而不是输入流,所以你必须阅读它们!
  2. 您必须在流程正在运行时阅读。在读取流之前等待进程完成会导致死锁,因为进程输出缓冲区已满,正在等待父进程读取数据,而父进程正在等待子进程完成!

答案 1 :(得分:0)

创建.jar文件并将该文件添加到构建路径

答案 2 :(得分:0)

尝试

Process process = Runtime.getRuntime().exec("java " + filePath); // without .class
Scanner output = new Scanner(process.getInputStream());
while (output.hasNext) {
   String token = output.next();
   ...
}

答案 3 :(得分:0)

还有很多构建/编译工具,即Ant或Maven,您可以在编写自己的工具之前进行检查。

答案 4 :(得分:0)

其中一个选项是使用类加载器创建类的实例。类加载器可以将您的类作为字节数组,然后您可以创建它的实例并运行它。请参阅JDK文档中的this method

答案 5 :(得分:0)

这是一个示例应用程序,它将编译Java源文件,加载类,实例化实例,并打印出类HelloWorld的toString()。我相信你在classpath上需要tools.jar。示例代码需要src文件夹中的源文件。类路径上需要src文件夹,因为默认情况下会生成.class文件。

要更好地控制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来加载和实例化类。确保ClassLoader具有最小权限。