Как известно, некоторые JIT позволяют переупорядочивать для инициализации объекта, например,
someRef = new SomeObject();
можно разложить на следующие этапы:
objRef = allocate space for SomeObject; //step1
call constructor of SomeObject; //step2
someRef = objRef; //step3
JIT-компилятор может изменить порядок ниже:
objRef = allocate space for SomeObject; //step1
someRef = objRef; //step3
call constructor of SomeObject; //step2
а именно, step2 и step3 могут быть переупорядочены компилятором JIT. Несмотря на то, что это теоретически допустимое переупорядочение, я не смог воспроизвести его с помощью Hotspot (jdk1.7) под платформой x86.
Итак, есть ли переупорядочение инструкций, сделанное компилером Jots Hotspot JIT, которое можно воспроизвести?
Обновление: Я сделал test на моей машине (Linux x86_64, JDK 1.8.0_40, i5-3210M), используя следующую команду:
java -XX:-UseCompressedOops -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand="print org.openjdk.jcstress.tests.unsafe.UnsafePublication::publish" -XX:CompileCommand="inline, org.openjdk.jcstress.tests.unsafe.UnsafePublication::publish" -XX:PrintAssemblyOptions=intel -jar tests-custom/target/jcstress.jar -f -1 -t .*UnsafePublication.* -v > log.txt
и я вижу, что инструмент сообщил что-то вроде:
[1] 5 ACCEPTABLE Объект опубликован, видимо, видимо не менее 1 поля.
Это означало, что поток наблюдателей видел неинициализированный экземпляр MyObject.
Однако я не видел код сборки, сгенерированный как @Ivan's:
0x00007f71d4a15e34: mov r11d,DWORD PTR [rbp+0x10] ;getfield x
0x00007f71d4a15e38: mov DWORD PTR [rax+0x10],r11d ;putfield x00
0x00007f71d4a15e3c: mov DWORD PTR [rax+0x14],r11d ;putfield x01
0x00007f71d4a15e40: mov DWORD PTR [rax+0x18],r11d ;putfield x02
0x00007f71d4a15e44: mov DWORD PTR [rax+0x1c],r11d ;putfield x03
0x00007f71d4a15e48: mov QWORD PTR [rbp+0x18],rax ;putfield o
Кажется, что здесь нет переупорядочения компилятора.
Update2: @Иван поправил меня. Я использовал неправильную команду JIT для захвата кода сборки. После исправления этой ошибки я могу сделать снизу код сборки:
0x00007f76012b18d5: mov DWORD PTR [rax+0x10],ebp ;*putfield x00
0x00007f76012b18d8: mov QWORD PTR [r8+0x18],rax ;*putfield o
; - org.openjdk.jcstress.tests.unsafe.generated.UnsafePublication_jcstress$Runner_publish::[email protected] (line 156)
0x00007f76012b18dc: mov DWORD PTR [rax+0x1c],ebp ;*putfield x03
По-видимому, компилятор сделал переупорядочение, которое вызвало небезопасную публикацию.