Java验证程序和解决方案

时间:2012-05-12 15:26:47

标签: java jvm resolution verification

假设我们有以下定义:

public class Test {

    public static void main(String[] args) {
        System.out.println("------MAIN METHOD------");
        A a = new B();  
        a.a = 3;
        System.out.println(a.a);
    }

}

    public class A {

        int a;

        public void g(){
            System.out.println(a);
        }

    }

public class B extends A {}

现在,假设我们构建上述内容,然后将B修改为

public class B {}

并重建JUST B.当我们关闭验证器时,方法打印3!据我所知,验证者没有发现这一点,A中的洗脱检查有一个字段a,情况就是这样......但是B没有为整数字段分配空间a!它写在哪里呢?

2 个答案:

答案 0 :(得分:4)

内存中的java对象被填充并对齐至少16个字节长,因此在仅包含int字段的类中有一些未使用的空间。如果你向A添加更多字段,你可能会覆盖其他对象的存储空间,但这也可能不会立即导致崩溃,尤其是在这样一个立即退出的短应用程序中。

通过声明这样的类可以获得更多乐趣:

public class A {
    int[] a = new int[1];
}

public class B {
    int a = 0x01020304;
}

public class Test {
    public static void main(String[] args) {
        A a = new B();  
        a.a[0] = 3;
        System.out.println(a.a[0]);
    }
}

通过java -Xverify:none Test执行此代码的结果应该导致如下所示的JVM错误,但原则上它应该允许您在java进程的内存中随处写入:

------MAIN METHOD------
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f9147d69532, pid=14785, tid=140262017775360
#
# JRE version: 6.0_26-b03
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# j  Test.main([Ljava/lang/String;)V+17

答案 1 :(得分:0)

如果你真的只重建了B,A a = new B();应该失败并且ClassCastException,因为B将不再与A运行时兼容。检查重建的B是否在运行时类路径中,这是唯一的B那里。

更正:VerifyError,而不是ClassCastException

编译并运行原始代码: C:\ TMP>%JAVA_HOME%\ bin \ javac -s。 *的.java C:\ TMP>%JAVA_HOME%\ bin \ java -cp。测试 ------主要方法------ 3

然后更新B.java,重新编译,然后再次运行: C:\ TMP>%JAVA_HOME%\ bin \ javac -s。 B.java C:\ TMP>%JAVA_HOME%\ bin \ java -cp。测试 线程“main”中的异常java.lang.VerifyError:方法Test.main中的putfield中操作数堆栈上的错误类型([Ljava / lang / String;)V偏移量为18