为什么这两种获取布尔值的方法会有不同的结果?
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 != 0
和 x & 1
之间的区别可能会导致您描述的行为。
我建议首先使用 javap
来查看生成的字节码是什么样子,然后再检查您是否 运行将它们放在同一个 JVM 中。
但最后的建议是根本不要使用 Unsafe,尤其是不要通过写入超过字段占用的数据来覆盖堆上的数据。
我写了代码:
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 != 0
和 x & 1
之间的区别可能会导致您描述的行为。
我建议首先使用 javap
来查看生成的字节码是什么样子,然后再检查您是否 运行将它们放在同一个 JVM 中。
但最后的建议是根本不要使用 Unsafe,尤其是不要通过写入超过字段占用的数据来覆盖堆上的数据。