IntelliJ Idea tomcat热插拔失败:未实现架构更改VM不支持操作

时间:2015-01-16 16:11:44

标签: tomcat intellij-idea jvm jvm-hotspot hotswap

当我尝试在项目中使用已更改的方法主体重新加载类(热交换)时出现此错误。在一切正常之前,但突然停止,我不记得什么可能是一个原因。有什么奇怪我有另一个项目具有相同的设置和方法体的热插拔工作正常。

以下是 NOT-working 项目的配置:

enter image description here

enter image description here

我的虚拟机设置:

-XX:PermSize=512m
-XX:MaxPermSize=1024m
-Xms1024m
-Xmx2048m
-Dcatalina.home="C:\Programy\apache-tomcat-7.0.57"
-Djava.endorsed.dirs="C:\Programy\apache-tomcat-7.0.57\endorsed"
-javaagent:C:\Programy\apache-tomcat-7.0.57/lib/spring-instrument-3.1.2.RELEASE.jar
-Dspring.profiles.active=closeMonthTest
-Dnpk.jobs.enabled=true

这是我的工作项目的配置:

enter image description here

enter image description here

VM选项:

-XX:PermSize=512m
-XX:MaxPermSize=1024m
-Xms1024m
-Xmx2048m
-Dcatalina.home="C:\Programy\apache-tomcat-7.0.57"
-Djava.endorsed.dirs="C:\Programy\apache-tomcat-7.0.57\endorsed"
-javaagent:C:\Programy\apache-tomcat-7.0.57/lib/spring-instrument-3.1.2.RELEASE.jar
-Dspring.profiles.active=test

1 个答案:

答案 0 :(得分:9)

如果没有代码,很难找到根本原因。但是,我可以编写一个人工测试用例,即使我只是更改方法体,Java编译器也会创建合成方法:

public class Test {

    static class Inner {

        private void getPrivate(int i) {
            Thread.dumpStack();
        }

        private void getPrivate() {
            Thread.dumpStack();
        }
    }

    public static void main(String[] args) {
        Inner inner = new Inner();
        inner.getPrivate(0);
        inner.getPrivate();
    }
}

此效果通过合成方法访问$ 000来解释,javac生成该方法以允许访问Inner类的私有成员。

javac Test.java 
javap -c -private Test\$Inner
  ...
  static void access$000(edu.Test$Inner, int);
    Code:
       0: aload_0       
       1: iload_1       
       2: invokespecial #2                  // Method getPrivate:(I)V
       5: return        

  static void access$100(edu.Test$Inner);
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method getPrivate:()V
       4: return        

让我们改变主要方法中两种方法的顺序:

    public static void main(String[] args) {
        Inner inner = new Inner();
        inner.getPrivate();
        inner.getPrivate(0);
    }

结果,编译器更改了方法签名。

  ...
  static void access$000(edu.Test$Inner);
    Code:
       0: aload_0       
       1: invokespecial #2                  // Method getPrivate:()V
       4: return        

  static void access$100(edu.Test$Inner, int);
    Code:
       0: aload_0       
       1: iload_1       
       2: invokespecial #1                  // Method getPrivate:(I)V
       5: return     

从HotSwap的角度来看,此更改被禁止,因为方法access$000的签名已更改。