在运行时编写和实现新的Java类文件

时间:2011-03-30 23:47:04

标签: java class file runtime

是否有可能以某种方式将新Java类导入到正在运行的程序中并使用它?

我可以让程序创建一个类型为'.java'的新文件,然后将其包含在项目文件中并引用它而不必重新启动程序吗?

以下是我的意思的一个例子:

import java.io.*;

public class Program {

File JClass = new File("JClass.java");
public static BufferedWriter out = null;

    public static void main(String[] args) {
        try {
            out = new BufferedWriter(new FileWriter("JClass.java"));
            out.write("public abstract class JClass {");
            out.newLine();
            out.newLine();
            out.write("    public void printSomething(String a) {");
            out.newLine();
            out.write("        System.out.println(a);");
            out.newLine();
            out.write("    }");
            out.newLine();
            out.write("}");
            out.close();
        } catch (IOException e)
        {
            System.exit(-1);
        }

        //Somehow import JClass.java as a class here

        JClass.printSomething("Yay! It worked!");
    }

}

产生的'JClass.java'文件:

public abstract class JClass {

    public void printSomething(String a) {
        System.out.println(a);
    }
}

同样,是否可以创建项目源文件之一的副本,编辑文件中的代码,然后以某种方式强制对正在运行的程序进行更改?

此时我对实际应用并不在意。我只是在探索与编程有关的不同想法。我也明白这可能是各种各样的灾难。编辑正在运行的代码,并且包括动态的类(我无法想象将检查错误,因为其他类是在构建项目时),可能会产生非常不可预测的结果。我只想玩弄这个想法。

那就是说,如果有人有任何有用的警告或注意事项,我将不胜感激。否则,如果人们不回应“这是一个坏主意”或“有更容易和更好的方法来解决问题”,我将不胜感激。我不是试图解决这个问题。我只是在探索这个想法。

那么,这可能吗?

4 个答案:

答案 0 :(得分:5)

Javassist将允许您在运行时修改现有类并创建新类。 http://www.csg.is.titech.ac.jp/~chiba/javassist/

在Javassist tutorial中,有一节用于从头开始定义新类。查看API以了解如何添加新方法等。查看Javassist API中的CtNewMethod.make

Javassist是JBoss用来实现面向方面编程的东西。

您还可以查看EATS(感兴趣的工具方法),它使用Javassist在运行时向现有方法添加新代码。 Eats不是发布版本,但它有效:o

JPDA提供了一些修改已经在JVM中加载和运行的类的机制。

答案 1 :(得分:2)

您应该使用ClassLoader

查看fly类加载

http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html

还有一些机制可以用来编译类,但这可能不会对你有用。

答案 2 :(得分:0)

你真的想要一个编译器 - 看一下java.lang.Compiler:

http://download.oracle.com/javase/6/docs/api/java/lang/Compiler.html

您可以通过编译新的.class文件来以这种方式加载不同的类。

这不允许您更改已加载的类。为此,您还需要一个java.lang.instrument.ClassFileTransformer,并且必须在运行时在命令行中指定。

回答其他一些问题:

  • 如果文件是从.java编译的,那么它将与在别处编译的文件进行相同的检查。
  • 如果使用合适的工具(例如BCEL或ASM)创建字节代码,那么它仍会经过多次检查以证明它在内部是一致的。
  • 如果您更改正在运行的课程,则您可以更改的内容有限。

答案 3 :(得分:0)

再向那里投掷一个:Eclipse Java Compiler。与BCEL,ASM或Jasmin不同,您不需要知道装配。 ECJ只是一个用Java编写的Java编译器。