如何即时更改更改类行为?

时间:2012-05-26 13:29:14

标签: java jvm on-the-fly

我正在尝试编辑一个类文件,并在运行时将其提供给JVM。 这可能,我该怎么做?

例如:

main() {
    for (int i=0;i<10;i++) {
        NewClass.method();
        //ask user if to continue..
    }
}

public class NewClass() {
    static void method() {
        sysout("hi");
    }
}

当执行此循环时,我想更改文件NewClass()并将其加载到JVM中,以便打印“bye”。

以下是完整的代码:

try {
    for (int iCount = 0; iCount < 10; iCount++) {
        BufferedReader br = new BufferedReader(new InputStreamReader(
                System.in));
        System.out.print("Enter which method:");
        int i = Integer.parseInt(br.readLine());
        System.out.println(i);
        if (i == 1) {
            Called.calledMethod1();
        } else {
            Called.calledMethod2();
        }
    }
} catch (NumberFormatException nfe) {
    System.err.println("Invalid Format!");
}

我想运行一个类的main方法,并且在运行时我想引用另一个类,编辑它,并引用第二个类的相同方法并获得不同的输出。

想要:

  1. 停止jvm
  2. 编辑代码
  3. 再次运行代码。
  4. 我想

    1. 在运行时编辑代码,并立即反映更改。

1 个答案:

答案 0 :(得分:2)

您必须使用Java反射。使用反射,

  1. 使用Class forName method在运行时动态加载类。
  2. 在您获得的Class实例上使用invoke方法,您可以调用任何您想要的静态方法。
  3. 如果你的课程在设计时固定,你只需要先扭转第一点。一些代码:

    ...
    
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Enter which class:");
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    className=br.readLine()
    int results = compiler.run(null, null, null, className+".java");
    if(results == 0){
    
        Class clazz = Class.forName(className+".class");
        System.out.print("Compiled successfully.Enter which method:");
        Object returnValue=clazz.getMethod(br.readLine()).invoke(null);
    }
    ...
    

    但要注意安全问题:上面的代码允许任何人在运行时访问每个类的每个静态方法。如果安全性是您关注的问题之一,那么最好先验证从控制台收到的输入并测试它们是否与您通过控制台提供的类方法相匹配。

    修改

    在我阅读你的评论后,我更了解你的问题。如果要定位Java 6,为了在运行时编译类,可以使用Java Compiler object。我编辑代码以包含JavaCompiler用法。