【问题标题】:Writing and implementing new Java class files during run-time在运行时编写和实现新的 Java 类文件
【发布时间】:2011-03-30 23:47:04
【问题描述】:

是否有可能以某种方式将新的 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);
    }
}

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

目前我不太关心实际应用。我只是在探索我对编程的不同想法。我也明白这有可能引发各种灾难。编辑正在运行的代码,并在运行中包括类(我不认为会像构建项目时检查其他类一样检查错误),可能会产生非常不可预测的结果。我只是想玩弄这个想法。

也就是说,如果有人有任何有用的警告或需要注意的事情,我将不胜感激。否则,如果人们不回答“这是个坏主意”或“有更简单更好的方法来解决问题”,我将不胜感激。我不是想解决这个问题。我只是在探索这个想法。

那么,这可能吗?

【问题讨论】:

    标签: java class file runtime


    【解决方案1】:

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

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

    JBoss 使用 Javassist 来实现面向方面的编程。

    您还可以查看EATS(仪器方法会很有趣),它利用 Javassist 在运行时向现有方法添加新代码。 Eats 没有发布版本,但它可以工作:o

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

    【讨论】:

    • ASM 和 CGLIB 是类似的库。这种方法被广泛使用,并且可能是动态创建代码的“最佳”方式。
    • Eww,EATS 使用匈牙利符号。 :-(
    【解决方案2】:

    您应该查看使用 ClassLoader 动态加载类

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

    您还可以使用一些机制来编译类,但这可能对您没有用处。

    【讨论】:

      【解决方案3】:

      您实际上想要一个编译器 - 查看 java.lang.Compiler:

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

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

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

      回答您的其他一些问题:

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

      【讨论】:

        【解决方案4】:

        再扔一个:Eclipse Java Compiler。与 BCEL、ASM 或 Jasmin 不同,您不需要了解汇编。 ECJ 只是一个用 Java 编写的 Java 编译器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-23
          • 2023-03-08
          • 1970-01-01
          • 2018-11-06
          • 2016-05-31
          • 1970-01-01
          相关资源
          最近更新 更多