Почему эти два способа получить логическое значение имеют разные результаты? - PullRequest
0 голосов
/ 22 февраля 2020

Я написал коды:

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, он также дает разные результаты, первый - в затмении, а второй - в идее. eclispe идея

1 Ответ

0 голосов
/ 22 февраля 2020

Во-первых, вы используете небезопасное, что, как следует из названия, небезопасно, поэтому, когда вы видите подобные проблемы, вы не должны полагаться на такое поведение.

Вероятно, вы видите разницу в компиляторе или JVM между двумя IDE. Вы пишете значение Int (которое составляет 4 байта), и даже это работает только потому, что оно выполняется на машине с прямым порядком байтов, потому что первый байт находится там, где находится ненулевое значение. Делая это, вы можете уничтожить следующее значение в куче.

Учитывая, что представление логического значения не связано языком строго, может случиться так, что один компилятор генерирует байт-код для «равен ли он нулю», а другой рассматривает бит младшего разряда как зависимый включен, если он установлен; т.е. разница между x != 0 и x & 1, которая может дать поведение, которое вы описываете.

Я рекомендую использовать javap, чтобы посмотреть, как выглядит сгенерированный байт-код в первом случае, а затем проверить, что вы запускаете их в той же JVM, во-вторых.

Но окончательная рекомендация не является вообще использовать Unsafe и особенно не перезаписывать данные в куче, записывая больше, чем займет поле.

...