我写了代码:
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
首先,您使用的是不安全的方法,顾名思义,这是不安全的事情-因此,当您看到此类问题时,就不应依赖该行为。
您可能看到的是两个IDE之间的编译器或JVM有所不同。您正在写一个Int值(4个字节),即使这样也只能工作,因为它是在一点字节序的机器上运行的,因为第一个字节是非零值所在的位置。这样做可能会浪费堆中的下一个值。
鉴于布尔值的表示没有严格地受语言约束,可能是一个编译器正在为“是否为零”生成字节码,而另一个正在查看低阶位以取决于它是否为组;即x != 0
和x & 1
之间的差异可能会导致您描述的行为。
我建议使用javap
首先查看生成的字节码,然后再检查是否在同一JVM中运行它们。
但是最终的建议是根本不要使用Unsafe,尤其是不要通过写超出字段所需的内容来覆盖堆上的数据。