为什么这两种获取布尔值的方法会有不同的结果?

问题描述 投票:0回答:1

我写了代码:

public class StaticBooleanDemo {
  private static boolean flag;

  public static boolean getFlag(){
    return flag;
  }

  public static void main (String[] args ) throws Exception{
    Unsafe unsafe = MyJVMUtil.getUnsafe();
    Field field = StaticBooleanDemo.class.getDeclaredField("flag");
    unsafe.putInt(StaticBooleanDemo.class,
    unsafe.staticFieldOffset(field),2);
    System.out.println("getFlag():"+getFlag());
    System.out.println("flag:"+flag);

  } 

}
public class MyJVMUtil {
   public static Unsafe getUnsafe(){
    try {
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        return unsafe;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
}

我有两个结果,第一个为假,第二个为真。我很困惑,想知道为什么变量标记有两个不同的结果?但是当我在两个IDE中运行它时,它也会给出不同的结果,第一个是Eclipse,第二个是想法。eclispeidea

java jvm unsafe
1个回答
0
投票

首先,您使用的是不安全的方法,顾名思义,这是不安全的事情-因此,当您看到此类问题时,就不应依赖该行为。

您可能看到的是两个IDE之间的编译器或JVM有所不同。您正在写一个Int值(4个字节),即使这样也只能工作,因为它是在一点字节序的机器上运行的,因为第一个字节是非零值所在的位置。这样做可能会浪费堆中的下一个值。

鉴于布尔值的表示没有严格地受语言约束,可能是一个编译器正在为“是否为零”生成字节码,而另一个正在查看低阶位以取决于它是否为组;即x != 0x & 1之间的差异可能会导致您描述的行为。

我建议使用javap首先查看生成的字节码,然后再检查是否在同一JVM中运行它们。

但是最终的建议是根本不要使用Unsafe,尤其是不要通过写超出字段所需的内容来覆盖堆上的数据。

© www.soinside.com 2019 - 2024. All rights reserved.