9

我在使用 Intellij IDEA 社区版中的热插拔功能时遇到了麻烦。我的是 v 14.1.4。

每次我启动调试并更改 java 代码后,我已经单击了重建项目并在确认重新加载类时按“是”。Intellij 报告更改的类已重新加载,但应用程序结果与以前相同。我只是在尝试最简单的 Java 应用程序(即不在 Tomcat、applet 等场景中),其中包含简单的东西System.out.println,例如字符串 concats 等。我在调试模式下更改的只是方法主体代码,而不是方法签名/名称. 我无法得到它。

在 Eclipse 中,我只是直接更改代码并按保存,然后它就可以工作了。

什么地方出了错?

(评论:

事实上,我正在尝试使用 DCEVM 来更改结构(例如更改类名、方法名、添加方法等),认为它可以解决 Intellij 中发现的热插拔问题。不用说,它没有用。

在eclipse中,我成功使用了DCEVM,并且可以在调试过程中更改方法名。

我进一步尝试了 hotswap-agent ,但它仍然不起作用;我看到一篇文章说 IDE 必须通过端口 5000 JDPA 连接到 JVM,但无论我如何尝试,Intellij 控制台显示它仍然通过随机端口(下面的 51018)连接:

"C:\Program Files\Java\jdk1.8.0_60\bin\java" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:51018...."

连接到目标VM,地址:'127.0.0.1:51018',传输:'socket'

是否可以强制它通过一个特定端口连接?在运行/调试配置中添加DEBUG_OPT环境变量不起作用)

4

1 回答 1

7

在找到 Jetbrains 对问题请求的反馈后,发现这是 Intellij 的设计行为:

来自 Jetbrains 的问题请求的反馈

换句话说,问题与我如何测试热交换有关:

public class Main {
//    /*
    public static String getName() {
        return "James"; // <=== (2)
    }

    //*/
    public static void main(String[] args) {
        System.out.println("Hello " + getName()); // <=== (1)
    }
}
  1. 由于 Intellij 的行为是“在 VM 退出过时的堆栈框架之前仍然使用旧代码”(与 Eclipse 相比的行为不同),如果在 (1) 处将“Hello”更改为“Bye”,新代码将永远不会被执行——新代码只有在第二次调用 main() 时才能再次执行,这是不可能的,因为应用程序已经终止

  2. 如果是 (2) 被更改(例如,用“Sean”替换“James”)而不是 (1),则在执行光标被放置在 (1) 处的断点停止期间(因此没有t 已输入 getName()),然后重新加载该类,您将运行新代码(打印“Sean”)

DCEVM 也工作得很好,使用相同的方式来测试热插拔

您还可以在堆栈跟踪窗口中使用“丢帧”来使当前语句回滚到方法的开头(main() 除外)——事实上,这与 Eclipse 中的行为相同。

于 2015-09-13T12:18:10.837 回答