我写的代码:
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中,第二个是在idea中。 eclispe idea
最佳答案
首先,您使用的是不安全,顾名思义,这不是一件安全的事情 - 所以当您看到这样的问题时,您不应该依赖这种行为。
您可能看到的是两个 IDE 之间编译器或 JVM 的差异。您正在编写一个 Int 值(4 个字节),即使这样也只能起作用,因为它是在小端机器上运行的,因为第一个字节是非零值所在的位置。通过这样做,您可能会丢弃堆上的下一个值。
鉴于 boolean 值的表示形式并未严格受到语言的限制,可能一个编译器正在生成“是否为零”的字节码,而另一个编译器正在查看低位以取决于它是否为零已设置;即 x != 0
和 x & 1
之间的差异可以给出您所描述的行为。
我建议使用 javap
来查看生成的字节码在第一个实例中的样子,然后检查您是否在同一个 JVM 中运行它们。
但最终的建议是根本不要使用 Unsafe,尤其是不要通过写入超过字段占用的内容来覆盖堆上的数据。
关于java - 为什么这两种获取 boolean 值的方法会得到不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60348436/