java - 为什么这两种获取 boolean 值的方法会得到不同的结果?

标签 java 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;
}
}

我得到两个结果,第一个是假的,第二个是真的。我很困惑,想知道为什么变量标志有两种不同的结果? 但是当我在两个IDE中运行它时,它也给出了不同的结果,第一个是在eclipse中,第二个是在idea中。 eclispe idea

最佳答案

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

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

鉴于 boolean 值的表示形式并未严格受到语言的限制,可能一个编译器正在生成“是否为零”的字节码,而另一个编译器正在查看低位以取决于它是否为零已设置;即 x != 0x & 1 之间的差异可以给出您所描述的行为。

我建议使用 javap 来查看生成的字节码在第一个实例中的样子,然后检查您是否在同一个 JVM 中运行它们。

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

关于java - 为什么这两种获取 boolean 值的方法会得到不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60348436/

相关文章:

java - 2 HashMap 之间的相等性

java - GWT 中的客户端时区支持

jvm - 运行 StarTeam 2008 Release 2 客户端时出现 “Could not create the Java virtual machine” 错误

Java VirtualMachine.loadAgent 仅一次加载代理

使用不安全代码的 C# 位图图像屏蔽

java - Sonar 标志 "Bad practice": Usage of GetResource in XYZ may be unsafe if class is extended

java - 如何从 IP 范围中获取单独的连续 IP block ?

java - 无法完成Gradle执行: cause

compiler-construction - 如何创建 JVM 编程语言?

c# - C# 中 GUID 的 pInvoke 方法