JVM从入门到精通(四):内存屏障与JVM指令,对象的内存布局
JMM
硬件層數(shù)據(jù)一致性
協(xié)議很多,intel 用MESI
https://www.cnblogs.com/z00377750/p/9180644.html
現(xiàn)代CPU的數(shù)據(jù)一致性實(shí)現(xiàn) = 緩存鎖(MESI …) + 總線鎖
讀取緩存以cache line為基本單位,目前64bytes
位于同一緩存行的兩個(gè)不同數(shù)據(jù),被兩個(gè)不同CPU鎖定,產(chǎn)生互相影響的偽共享問題
偽共享問題:JUC/c_028_FalseSharing
使用緩存行的對齊能夠提高效率
亂序問題
CPU為了提高指令執(zhí)行效率,會在一條指令執(zhí)行過程中(比如去內(nèi)存讀數(shù)據(jù)(慢100倍)),去同時(shí)執(zhí)行另一條指令,前提是,兩條指令沒有依賴關(guān)系
寫操作也可以進(jìn)行合并
https://www.cnblogs.com/liushaodong/p/4777308.html
JUC/029_WriteCombining
亂序執(zhí)行的證明:JVM/jmm/Disorder.java
原始參考:https://preshing.com/20120515/memory-reordering-caught-in-the-act/
如何保證特定情況下不亂序
硬件內(nèi)存屏障,針對X86:
sfence: store| 在sfence指令前的寫操作當(dāng)必須在sfence指令后的寫操作前完成。
lfence:load | 在lfence指令前的讀操作當(dāng)必須在lfence指令后的讀操作前完成。
mfence:modify/mix | 在mfence指令前的讀寫操作當(dāng)必須在mfence指令后的讀寫操作前完成。
原子指令,如x86上的”lock …” 指令是一個(gè)Full Barrier,執(zhí)行時(shí)會鎖住內(nèi)存子系統(tǒng)來確保執(zhí)行順序,甚至跨多個(gè)CPU。Software Locks通常使用了內(nèi)存屏障或原子指令來實(shí)現(xiàn)變量可見性和保持程序順序
JVM級別如何規(guī)范(JSR133)
LoadLoad屏障:
對于這樣的語句Load1; LoadLoad; Load2,
在Load2及后續(xù)讀取操作要讀取的數(shù)據(jù)被訪問前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。
StoreStore屏障:
對于這樣的語句Store1; StoreStore; Store2
在Store2及后續(xù)寫入操作執(zhí)行前,保證Store1的寫入操作對其它處理器可見。
LoadStore屏障:
對于這樣的語句Load1; LoadStore; Store2,
在Store2及后續(xù)寫入操作被刷出前,保證Load1要讀取的數(shù)據(jù)被讀取完畢。
StoreLoad屏障:
對于這樣的語句Store1; StoreLoad; Load2,
在Load2及后續(xù)所有讀取操作執(zhí)行前,保證Store1的寫入對所有處理器可見。
volatile 的實(shí)現(xiàn)細(xì)節(jié)
字節(jié)碼層面
ACC_VOLATILE
JVM層面
對于volatile內(nèi)存區(qū)的讀寫,都加屏障:
StoreStoreBarrier
volatile 寫操作
StoreLoadBarrier
LoadLoadBarrier
volatile 讀操作
LoadStoreBarrier
OS和硬件層面
https://blog.csdn.net/qq_26222859/article/details/52235930
使用hsdis工具 - HotSpot Dis Assembler
windows lock 指令實(shí)現(xiàn) | MESI實(shí)現(xiàn)
synchronized實(shí)現(xiàn)細(xì)節(jié)
ACC_SYNCHRONIZED
monitorenter monitorexit
C C++ 調(diào)用了操作系統(tǒng)提供的同步機(jī)制,在win和linux上不同
X86 : lock cmpxchg / xxx
lock是處理多處理器之間的總線鎖問題
https://blog.csdn.net/21aspnet/article/details/88571740
使用synchronized的例子:
生成的JVM指令:
Java并發(fā)內(nèi)存模型
as-if-serial
? 不管如何重排序,單線程執(zhí)行結(jié)果不會改變,看起來像是串行的一樣
對象的內(nèi)存布局
觀察虛擬機(jī)配置
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=266536512 -XX:MaxHeapSize=4264584192 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC java version "1.8.0_241" Java(TM) SE Runtime Environment (build 1.8.0_241-b07) Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)對象在內(nèi)存中的存儲布局?
(經(jīng)過試驗(yàn)證明)一個(gè)Object是16字節(jié),8(對象頭)+4(開啟壓縮時(shí)的對象指針)+padding(對齊)
普通對象
Oops Ordinary Object Pointers
數(shù)組對象
對象頭具體包括什么?
問題:為什么GC年齡默認(rèn)為15?因?yàn)榉执挲g只有4bit,可以表示最大的數(shù)就是15
當(dāng)一個(gè)對象計(jì)算過identityHashCode之后,不能進(jìn)入偏向鎖狀態(tài)
對象怎么定位?
https://blog.csdn.net/clover_lily/article/details/80095580
《深入理解Java虛擬機(jī)》
對象在內(nèi)存中的哪個(gè)區(qū)域,分配過程
總結(jié)
以上是生活随笔為你收集整理的JVM从入门到精通(四):内存屏障与JVM指令,对象的内存布局的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL调优(三):索引基本实现原理及
- 下一篇: 多线程与高并发(五):强软弱虚四种引用以