我们知道,一些JIT允许重新排序对象初始化,例如,
someRef = new SomeObject();
Run Code Online (Sandbox Code Playgroud)
可以分解为以下步骤:
objRef = allocate space for SomeObject; //step1
call constructor of SomeObject; //step2
someRef = objRef; //step3
Run Code Online (Sandbox Code Playgroud)
JIT编译器可能会重新排序如下:
objRef = allocate space for SomeObject; //step1
someRef = objRef; //step3
call constructor of SomeObject; //step2
Run Code Online (Sandbox Code Playgroud)
即,步骤2和步骤3可以由JIT编译器重新排序.虽然这在理论上是有效的重新排序,但我无法使用x86平台下的Hotspot(jdk1.7)重现它.
那么,Hotspot JIT comipler是否可以重现任何指令重新排序?
更新:我使用以下命令在我的机器(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
Run Code Online (Sandbox Code Playgroud)
我可以看到该工具报告的内容如下:
[1] 5可接受对象已发布,至少有1个字段可见.
这意味着观察者线程看到了一个未初始化的MyObject实例.
但是,我没有看到像@ Ivan那样生成的汇编代码:
0x00007f71d4a15e34: mov r11d,DWORD PTR …Run Code Online (Sandbox Code Playgroud) 'intrinsify'是否意味着JVM的源代码有些"保守",但JVM编译器可以在JVM预热时进行一些优化?例如,
UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
UnsafeWrapper("Unsafe_SetOrderedObject");
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
OrderAccess::release();
if (UseCompressedOops) {
oop_store((narrowOop*)addr, x);
} else {
oop_store((oop*)addr, x);
}
OrderAccess::fence(); <==There is a full memory barrier to ensure visibility which is NOT strictly required
UNSAFE_END
Run Code Online (Sandbox Code Playgroud)
putOrderedObject不需要确保immediate visiblity,但我们可以看到存储器附加了一个完整的内存屏障到指定的对象,所以我说JVM是conservative,但是JIT编译器可以在运行时优化这个内存屏障,这就是所谓的instrinsify,我是对的?
许多人问这样的类似问题,但他们的答案都没有让我满意.我非常确定的唯一两个重新排序规则如下:
但是,对于同步块之前或之后的那些操作,它们是否可以移动到临界区?对于这个问题,我发现有些相反.例如,cookbook说编译器会在MonitorEnter之后和MonitorExit之前插入一些障碍:
MonitorEnter
(any other needed instructions go here )
[LoadLoad] <===MB1:Inserted memory barrier
[LoadStore] <===MB2:Inserted memory barrier
(Begin of critical section)
....
(end of critical section)
[LoadStore] <===MB3:Inserted memory barrier
[StoreStore] <===MB4:Inserted memory barrier
(any other needed instructions go here )
MonitorExit
Run Code Online (Sandbox Code Playgroud)
根据以上编译器的位置并给出下面的伪代码:
Load a;
Load b;
Store 1;
Store 2;
MonitorEnter
(any other needed instructions go here )
[LoadLoad] <===MB1
[LoadStore] <===MB2
(Begin of critical section)
....
(end of …Run Code Online (Sandbox Code Playgroud) ARM 处理器是否有无效队列?我查找了 ARM 架构参考手册[ https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf],但它没有提到“无效队列”(它确实提到了“写入缓冲区”),那么这是否意味着ARM没有无效队列?