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

Why are there different results with these two ways to get the boolean?

我写了代码:

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;
}
}

我得到了两个结果,第一个是假的,第二个是真的。我很纳闷,为什么变量flag会有两种不同的结果? 但是当我 运行 它在两个 IDE 中时,它也给出了不同的结果,第一个是在 eclipse 中,第二个是在 idea 中。 eclispe idea

首先,您使用的是不安全行为,顾名思义,这不是一件安全的事情 - 所以当您看到此类问题时,您不应该依赖这种行为。

您可能看到的是两个 IDE 在编译器或 JVM 方面的差异。您正在写一个 Int 值(4 个字节),即使这样也只能工作,因为它在小端机器上是 运行,因为第一个字节是非零值所在的位置。这样做可能会破坏堆上的下一个值。

鉴于布尔值的表示不受语言的严格限制,可能是一个编译器正在为“它是否为零”生成字节码,而另一个编译器正在查看低阶位以依赖于如果已设置;即 x != 0x & 1 之间的区别可能会导致您描述的行为。

我建议首先使用 javap 来查看生成的字节码是什么样子,然后再检查您是否 运行将它们放在同一个 JVM 中。

但最后的建议是根本不要使用 Unsafe,尤其是不要通过写入超过字段占用的数据来覆盖堆上的数据。