【问题标题】:How can I change change class behaviour on-the-fly?如何即时更改更改类行为?
【发布时间】:2012-05-26 13:29:14
【问题描述】:

我正在尝试编辑一个类文件并使其在运行时可供 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 中,以便它打印“再见”。

完整代码如下:

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!");
}

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

不想想要:

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

我想要

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

【问题讨论】:

  • 为了让你的工作更轻松,这里是完整的代码: try{ for(int iCount=0; iCount
  • 你应该把代码放在你的问题中。
  • 解释得更好:您希望能够在运行时动态加载一个类并执行其方法之一?
  • 我建议使用Scanner 从控制台读取。您是否真正关注类加载或向方法添加参数会解决您的问题?更具体。
  • 我想运行一个类的主要方法,当它运行时我想引用另一个类,编辑它并引用第二个类的相同方法以获得不同的输出。基本上我不想1.停止jvm,2.编辑代码,3.再次运行代码。我想1.在运行时编辑代码并反映更改。

标签: java jvm on-the-fly


【解决方案1】:

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

  1. 您在运行时使用Class forName method 动态加载一个类。
  2. 在您获得的 Class 实例上使用 invoke 方法,您可以调用任何您想为其命名的静态方法。

如果你的类在设计时是固定的,你只需要忽略第一点。一些代码:

...

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 的使用。

【讨论】:

  • 输入哪个类:调用编译成功。输入哪个方法:调用方法1 Oldsysoutmethod1 输入哪个类:调用编译成功。输入哪个方法:调用方法1 Oldsysoutmethod1 我想编辑相同的方法并得到Newsysoutmethod1,而无需重新运行主java程序。我还尝试在被调用的 java 文件中添加一个新方法并将该方法名称作为输入,但我得到了 NoSuchMethodException
  • 是否可以再次对同一个类文件进行class.forname ..通过卸载旧的类文件并再次加载具有编辑内容的相同文件名..
  • Pawan:卸载类并重新加载更改的版本没有简单的解决方案。也许开发自己的类加载器,但不是一件容易的事。一个非常简单的解决方案(如果你可以接受的话)是在每次编辑时更改你的类的名称,或者更改它的包名。
  • 我正在关注类名想法的变化,因为我想要它只是为了调试目的:) 谢谢..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 2020-06-17
  • 2017-01-26
  • 2018-08-13
  • 2015-08-07
  • 1970-01-01
相关资源
最近更新 更多