深入理解Java虛擬機(jī)

[學(xué)習(xí)筆記] 深入理解Java虛擬機(jī)

標(biāo)簽(空格分隔): java


第二部分.自動(dòng)內(nèi)存管理機(jī)制

2.java內(nèi)存區(qū)域與內(nèi)存溢出異常

<center>
java內(nèi)存區(qū)域
java內(nèi)存區(qū)域

</center>

2.1.方法區(qū)(永久代)

  • 存放:
    • 類常量
    • 字符串常量
    • 靜態(tài)變量

2.2.堆(內(nèi)存中最大的一塊)

堆內(nèi)存劃分
堆內(nèi)存劃分
  • 存放:
    • 實(shí)例
    • 數(shù)組元素
  • 劃分:
    • 年輕代(young generation):新創(chuàng)建對(duì)象的存放區(qū)域.當(dāng)年輕帶被用完時(shí),會(huì)觸發(fā)Minor GC.
      • 伊甸區(qū)(eden)
      • 幸存區(qū)0(survivor0)
      • 幸存區(qū)1(survicor1)
        年輕代特點(diǎn):
    • 老年代(old ggeneration):包含了長(zhǎng)期存活的對(duì)象和經(jīng)過多次MinorGC后依然存活下來的對(duì)象.通過老年代被占滿的時(shí)候進(jìn)行MajorGC.Major GC會(huì)花更多的實(shí)踐.
    • 永久代(Perm):
  • Stop the World事件
    所有的來及回收事件都是stop the world事件,因?yàn)樗械膽?yīng)用線程都會(huì)停下來直到操作完成.
    因?yàn)槟贻p代里面的對(duì)象都是臨時(shí)對(duì)象,執(zhí)行Minor GC非???,所以應(yīng)用不會(huì)受到Stop the World影響.

2.3.虛擬機(jī)棧

  • 存放:
    • 局部變量.
      • 注意:局部變量表
  • “棧幀”:每個(gè)方法創(chuàng)建的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀,并壓入幀棧.
    用于存放局部變量表、操作數(shù)、動(dòng)態(tài)連接、方法出口等信息.
  • 操作數(shù)棧
    java沒有寄存器,所有參數(shù)傳遞使用的操作數(shù)棧。
  • 棧上分配
    • 小對(duì)象(一般幾十個(gè)byte)在沒有逃逸的情況下,可以直接分配在棧上。
  • 棧、堆、方法區(qū)的交互:

注意
- 當(dāng)線程棧深度超過 虛擬機(jī)棧所允許的最大深度的時(shí)候,就會(huì)拋StackOverflowError.
- 如果虛擬機(jī)棧擴(kuò)展時(shí),無法獲取到足夠的內(nèi)存,就會(huì)拋OOM.

2.4.本地方法棧

  • 存放Native方法。
  • 在HotSpot中,本地方法棧已被歸入虛擬機(jī)棧。

2.5.程序寄存器

  • 存儲(chǔ):
    • 如果線程執(zhí)行的是一個(gè)java方法,那么存儲(chǔ)的是正在執(zhí)行的虛擬機(jī)的字節(jié)碼指令地址.
    • 如果線程執(zhí)行的時(shí)一個(gè)native方法,那么存儲(chǔ)的時(shí)undefined.
  • 特點(diǎn):
    • 存取速度非??欤绦虿豢煽?
    • 這塊區(qū)域沒有規(guī)定沒有任何OutOfMemory.

3.典型的垃圾回收算法

http://icyfenix.iteye.com/blog/715301

3.2 對(duì)象已死嗎?

java堆中幾乎存放了所有的對(duì)象,垃圾回收器在回收之前需要確定哪些對(duì)象還”活著“,哪些對(duì)象已經(jīng)”死了“

3.2.1 引用計(jì)數(shù)法(Java沒有使用)

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,效率高
缺點(diǎn): 無法處理循環(huán)引用
原理:給對(duì)象添加一個(gè)引用,每當(dāng)有一個(gè)地方引用這個(gè)對(duì)象的時(shí)候,計(jì)算器就+1,當(dāng)引用失效的時(shí)候,引用就-1,當(dāng)引用計(jì)算器=0的時(shí)候表示該對(duì)象不被引用。
    需要注意的是:引用計(jì)數(shù)器很難解決對(duì)象之間循環(huán)引用,所以主流java虛擬機(jī)沒有使用引用計(jì)數(shù)器來管理內(nèi)存。

3.2.2 可達(dá)性分析法

可達(dá)性分析法
可達(dá)性分析法
- 強(qiáng)引用:GC永遠(yuǎn)不會(huì)回收引用對(duì)象。
- 軟引用SoftReference:在內(nèi)存溢出之前,會(huì)進(jìn)行第二次回收,如果回收之后還沒有足夠的內(nèi)存,才會(huì)拋出OOM。
- 弱引用WeakReference:引用對(duì)象只能生存到下一次GC之前。
- 虛引用(幽靈引用、幻影引用)PhantomReference:唯一目的就是GC在回收時(shí)收到一個(gè)系統(tǒng)通知。

3.2.3 finalize

finalize只會(huì)被執(zhí)行一次。

一個(gè)對(duì)象真正被回收需要經(jīng)歷兩次標(biāo)記過程:
如果一個(gè)對(duì)象在可達(dá)性分析后沒有與GC ROOT相連接的引用鏈,那就被被第一次標(biāo)記并且進(jìn)行一次篩選:
如果finalize沒有被重寫或調(diào)用過,虛擬機(jī)會(huì)讓認(rèn)為“沒必要執(zhí)行”。
否則,會(huì)執(zhí)行finalize方法

finalize:
如果調(diào)用finalize方法,那么這個(gè)對(duì)象將會(huì)被放到一個(gè)隊(duì)列里面[虛擬機(jī)建立并執(zhí)行Finalizer線程執(zhí)行調(diào)用],等待被回收。

finalize是對(duì)象逃脫死亡命運(yùn)的最后機(jī)會(huì)。只要與引用鏈上的任何一個(gè)對(duì)象建立鏈接即可。

3.2.4方法區(qū)回收

  • 回收內(nèi)容:
    • 廢棄常量:沒有地方引用
    • 無用的類:
      需要同時(shí)滿足以下條件:
      1. java堆中沒有這個(gè)類的實(shí)例;
      2. 加載該類的ClassLoader已經(jīng)被回收;
      3. 該類的Class字節(jié)碼沒有任何地方被引用。沒有任何地方通過反射調(diào)用該類的方法。

3.3 垃圾收集算法

3.3.1. Mark-Sweep(標(biāo)記-清除算法)

- 最基礎(chǔ)的算法
- 最容易實(shí)現(xiàn)的算法
- 算法:分為兩個(gè)階段:標(biāo)記階段和清除階段。
    - 標(biāo)記階段:就是標(biāo)記出所有要被回收的對(duì)象。
    - 清除階段:回收被標(biāo)記的要被回收的內(nèi)存區(qū)域。
- 最大缺點(diǎn):容易產(chǎn)生內(nèi)存碎片。
標(biāo)記清除算法
標(biāo)記清除算法

3.3.2. Copying(復(fù)制算法)

- 為了解決Mark-Sweep算法的缺點(diǎn)。
- 算法:將內(nèi)存按容量劃分成大小相等的兩塊,每次只使用其中的一塊。
    當(dāng)內(nèi)存用完了,就將還存活的對(duì)象復(fù)制到另一塊內(nèi)存上,然后將已使用的內(nèi)存空間一次性清除掉,這樣一來就容易出現(xiàn)內(nèi)存碎片。
- 優(yōu)點(diǎn):算法簡(jiǎn)單,運(yùn)行高效而且還不容易出現(xiàn)內(nèi)存碎片。
- 缺點(diǎn):內(nèi)存使用代價(jià)高,因?yàn)槟軌蚴褂玫膬?nèi)存只有原來的一半。
Copy算法
Copy算法

3.3.3. Mark-Compact(標(biāo)記-整理算法)

- 為了解決Copy算法,充分利用內(nèi)存空間。
- 算法:標(biāo)記階段和Mark-Sweep算法一樣,但是完成標(biāo)記之后,他不是直接清除被標(biāo)記的內(nèi)存區(qū)域,而是將存活對(duì)象往一端移動(dòng),然后清除端外的區(qū)域。
Mark-Compact算法
Mark-Compact算法

3.3.4.Generational Colletion (分代收集算法)

- 目前大多數(shù)jvm采用的算法
- 算法核心思想:根據(jù)對(duì)象的存活周期將內(nèi)存劃分為若干個(gè)區(qū)域。
    一般情況下將堆內(nèi)存分為:新生代和老年代。
        - 新生代特點(diǎn):每次內(nèi)存垃圾回收時(shí),有大量?jī)?nèi)存對(duì)象要被回收。
        - 老年代特點(diǎn):每次垃圾回收時(shí),只有少量對(duì)象需要被回收。
- 目前大多數(shù)垃圾收集器:
    - 對(duì)于新生代都采用Copying算法。
        因?yàn)樾律看味加写罅繉?duì)象被回收,也就是說復(fù)制的次數(shù)較少,但是實(shí)際中并不是按1:1來劃分新生代的內(nèi)存空間。
        一般將新生代劃分為一塊較大的Eden區(qū)和兩塊較小的Survivor區(qū)(一般為8:1:1),每次使用Eden區(qū)和一塊Survivor區(qū)。當(dāng)進(jìn)行回收時(shí),一般都將Eden區(qū)和Survivor中還存活的對(duì)象復(fù)制到另一塊Survivor中,然后清除Eden區(qū)和剛才使用過的Survivor區(qū)。
    - 對(duì)于老年代都采用Mark-Compact算法。
        因?yàn)槔夏甏看位厥斩贾挥猩倭繉?duì)象回收。

3.4 hotspot算法的實(shí)現(xiàn)

3.4.1枚舉根節(jié)點(diǎn)

3.4.2安全點(diǎn)

3.4.3安全區(qū)

3.5 垃圾收集器

參考資料:
https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/

3.5.1 serial收集器(新生代串行收集器)

串行收集器運(yùn)行示意圖
串行收集器運(yùn)行示意圖
  • 特性:
    • 單線程,采用復(fù)制算法.
    • 簡(jiǎn)單高效
  • 基本原理:在它進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程,直到它收集結(jié)束.
  • 使用場(chǎng)景:Client模式下默認(rèn)的新生代收集器

3.5.2 ParNew 收集器

ParNew收集器運(yùn)行示意圖
ParNew收集器運(yùn)行示意圖

就是Serial收集器的多線程版本.

  • 特性:

    • 單CPU不如Serial收集器.
  • 基本原理:讓垃圾線程和用戶線程同時(shí)工作.

  • 使用場(chǎng)景:

    • 在Client模式下的首選.
    • 目前只能與CMS收集器配合工作.
  • XX:ParallelGCThreads:通過這個(gè)參數(shù)來設(shè)置GC線程數(shù)量.

  • 使用-XX:+UseConcMarkSweepGC選項(xiàng)后的默認(rèn)新生代收集器,也可以使用-XX:+UseParNewGC選項(xiàng)來強(qiáng)制指定它。

3.5.3 parallel scavenge 收集器(新生代并行回收收集器)“吞吐量?jī)?yōu)先收集器”

  • 特性:
    • 吞吐量?jī)?yōu)先收集器
  • 和ParNew收集器的區(qū)別:關(guān)注點(diǎn)不同
    其他收集器的關(guān)注點(diǎn)是:在垃圾收集時(shí)盡量縮短用戶線程的停頓時(shí)間.
    parallel scaveng的關(guān)注點(diǎn)是:達(dá)到一個(gè)可控的吞吐量.
    概念:吞吐量 = 代碼運(yùn)行時(shí)間/(代碼運(yùn)行時(shí)間+垃圾回收時(shí)間)
  • 基本原理:通過設(shè)置兩個(gè)參數(shù)來精準(zhǔn)控制吞吐量.
    • 最大垃圾收集停頓時(shí)間:-XX:MaxGCPauseMills
    • 直接設(shè)置吞吐量大?。?XX:GCTimeRadio

概念:
并行:指多條垃圾線程在并行工作,用戶線程處于等待狀態(tài).
并發(fā):垃圾收集線程和用戶線程同時(shí)運(yùn)行,垃圾線程在另一個(gè)CPU上運(yùn)行.

3.5.4 serial old 收集器(老年代串行收集器)

老年代串行收集器
老年代串行收集器
  • 特性:

    • 采用標(biāo)記-整理算法.
  • 在Server使用場(chǎng)景:

    • 在jdk1.5之前的版本和Parallel Scavenge配合使用.
    • 作為CMS收集器的備選預(yù)案.

3.5.5 parallel old 收集器(老年代并行回收收集器)

Prallel Scavenge / Parllel Old 收集器運(yùn)行示意圖
Prallel Scavenge / Parllel Old 收集器運(yùn)行示意圖
  • 特性:
    • 使用多線程和標(biāo)記-清理算法.

3.5.6 cms 收集器

Concurrent Mark Sweep


Concurrent Mark Sweep
Concurrent Mark Sweep
  • 特性:

    • 采用標(biāo)記-清理算法.
    • 以獲取最短停頓時(shí)間為目標(biāo).適用于互聯(lián)網(wǎng)網(wǎng)站、BS系統(tǒng)的服務(wù)器上。
  • 特點(diǎn):

    • 初始標(biāo)記[Stop-The-World]:Root可以直接關(guān)聯(lián)到的對(duì)象。
    • 并發(fā)標(biāo)記[和用戶線程一起]:主要標(biāo)記過程,標(biāo)記全部對(duì)象。
    • 重新標(biāo)記[Stop-The-World]:在正式清理前做修正。
    • 并發(fā)清理[和用戶線程一起]:基于標(biāo)記結(jié)果,清理對(duì)象。
  • 優(yōu)點(diǎn):并發(fā)收集、低停頓.

  • 缺點(diǎn):

    1. 對(duì)CPU相當(dāng)敏感。
    2. 無法處理浮動(dòng)垃圾。

3.5.7 g1 收集器

  1. 面向服務(wù)器端."標(biāo)記-整理"
  2. 分代收集:不需要配合其他GC收集器就能管理整個(gè)GC堆。
  3. 空間整合
  4. 可預(yù)測(cè)的停頓
  • 特點(diǎn):
    • 初始標(biāo)記:標(biāo)記下GC Roots能直接關(guān)聯(lián)到的對(duì)象,需要停頓線程,但是耗時(shí)很短。
    • 并發(fā)標(biāo)記:需要從GC Roots中對(duì)對(duì)象進(jìn)行可達(dá)性分析,找出存活的對(duì)象。這個(gè)階段耗時(shí)較長(zhǎng),但可和用戶線程并發(fā)執(zhí)行。
    • 最終標(biāo)記:修正在程序并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分記錄。
    • 篩選回收:對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序,根據(jù)用戶所期望的GC停頓時(shí)間來指定回收計(jì)劃。
image_1bb13kfrh1l1l1puio61okhmqu9.png-27.9kB
image_1bb13kfrh1l1l1puio61okhmqu9.png-27.9kB

理解gc日志

垃圾收集器參數(shù)總結(jié)

  • 對(duì)象優(yōu)先在Eden區(qū)分配
  • 大對(duì)象直接進(jìn)入老年代
  • 長(zhǎng)期存活的對(duì)象進(jìn)入老年代

5、Java堆內(nèi)存開關(guān)

Java堆內(nèi)存開關(guān)
Java堆內(nèi)存開關(guān)

http://p3.pstatp.com/large/f740004e7f539099df0
image_1b6ha87jm1qfv1fc5kvj1vnr13qv9.png-364kB
image_1b6ha87jm1qfv1fc5kvj1vnr13qv9.png-364kB

第三部分.虛擬機(jī)執(zhí)行子系統(tǒng)

  1. 類文件結(jié)構(gòu)
  2. 虛擬機(jī)類加載機(jī)制
  3. 虛擬機(jī)字節(jié)碼執(zhí)行引擎
  4. 類加載及執(zhí)行子系統(tǒng)的案例與實(shí)戰(zhàn)

7 虛擬機(jī)類加載機(jī)制

7.1 類加載的時(shí)機(jī)

類的生命周期
類的生命周期
  • 加載
  • 驗(yàn)證
  • 準(zhǔn)備
  • 解析
  • 初始化
  • 使用
  • 卸載

加載、驗(yàn)證、準(zhǔn)備、初始化、卸載 這五個(gè)步驟的順序是確定的.
但是,解析 這一步可能在初始化之后完成,這是為了指出Java語(yǔ)言的運(yùn)行時(shí)綁定.

什么情況下需要開始類加載的第一個(gè)階段:加載?
1)new實(shí)例化對(duì)象的時(shí)候、讀取或設(shè)置一個(gè)靜態(tài)字段的時(shí)候、調(diào)用一個(gè)類的靜態(tài)方法的時(shí)候
2)反射調(diào)用的時(shí)候.
3)初始化一個(gè)類的時(shí)候,如果發(fā)起其父類還沒有被初始化的的時(shí)候,先觸發(fā)父類的初始化方法
4)
5)

7.2 類加載的過程

類加載的過程:加載、驗(yàn)證、準(zhǔn)備、解析、初始化

1)加載:
查找并加載類的二進(jìn)制數(shù)據(jù)
2)鏈接:
驗(yàn)證:確保被加載的類符合JVM規(guī)范、沒有安全性方面的問題.
準(zhǔn)備:為靜態(tài)變量分配內(nèi)存,并將其初始化為默認(rèn)值.
解析: 把虛擬機(jī)常量池中的符號(hào)引用轉(zhuǎn)換為直接引用.
3)初始化
為類的靜態(tài)變量賦予正確的初始化值.

7.2.1 加載

在加載階段,虛擬機(jī)主要完成以下3件事:
1. 通過一個(gè)類的全名獲取定義此類的二進(jìn)制字節(jié)流;
2. 將這個(gè)字節(jié)流所代表的靜態(tài)數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換成方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);
3. 在內(nèi)存中生成一個(gè)代表該類的Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口.

7.2.2 驗(yàn)證

7.3 類加載器

7.3.1 類與類加載器

7.3.2 雙親委派模型

  • 類加載器類型:

    1. 啟動(dòng)類加載器(Bootstrap ClassLoader):使用C++語(yǔ)言實(shí)現(xiàn),是虛擬機(jī)的一部分.
    2. 其他的類加載器:Java語(yǔ)言實(shí)現(xiàn),獨(dú)立于虛擬機(jī)外部,并且全部繼承于抽象類java.lang.ClassLoader。
  • 常用的系統(tǒng)提供的類加載器:

    • 啟動(dòng)類加載器(Boostrap ClassLoader)
    • 擴(kuò)展類加載器(Extension ClassLoader)
    • 應(yīng)用程序類加載器(Application ClassLoader)
  • 雙親委派模型

    <center>
    類加載器的雙親委派模型
    類加載器的雙親委派模型

    </center>

    • 雙親加載模型的工作過程:
      如果一個(gè)類加載器收到了類加載的請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器去完成,每一個(gè)層次的類加載器都是如此,因此所有的加載請(qǐng)求最終都應(yīng)該傳送到頂層的啟動(dòng)類加載器中,只有當(dāng)父加載器反饋?zhàn)约簾o法完成這個(gè)加載請(qǐng)求時(shí),自加載器才會(huì)嘗試自己去加載.

    • 為什么要使用雙親加載模型?雙親加載模型的好處?
      保證Java核心庫(kù)的安全性。
      (如果用戶自己編寫一個(gè)java.lang.Object的類,并放在程序的ClassPath中,那系統(tǒng)中將會(huì)出現(xiàn)多個(gè)不同的Object類,Java類型體系中最基礎(chǔ)的行為也就無法保證)

    • 資料:
      http://www.cnblogs.com/sunniest/p/4574080.html
      http://blog.csdn.net/huachao1001/article/details/52297075

  • 雙親委派模型的實(shí)現(xiàn)

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            //1.檢查請(qǐng)求的類是否已經(jīng)被加載過了
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                    // 如果父類為null,調(diào)用父類的加載器
                        c = parent.loadClass(name, false);
                    } else {
                    //如果父類不為null,則調(diào)用bootstap的類加載器
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    //如果父類加載器拋出ClassNotFoundException
                    //說明父類加載器無法完成加載請(qǐng)求
                }

                if (c == null) {
                    // 在父類加載器無法加載的時(shí)候
                    // 再調(diào)本身的findClass方法來進(jìn)行類加載
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

7.3.3 破壞雙親委派模型


第四部分.程序編譯與代碼優(yōu)化


第五部分.高效并發(fā)

12.java內(nèi)存模型與線程安全

12.1. 主內(nèi)存和工作內(nèi)存

- 內(nèi)存模型的主要目標(biāo):定義程序中各個(gè)變量的訪問規(guī)則。
- 線程對(duì)變量的所有操作(讀取、賦值等)都在工作內(nèi)存中進(jìn)行,不能再主內(nèi)存中操作。
- 線程間變量值的傳遞均需要通過主內(nèi)存來完成。
- 虛擬機(jī)可能會(huì)讓工作內(nèi)存優(yōu)先存儲(chǔ)于寄存器和高速緩存中,因?yàn)槌绦蜻\(yùn)行時(shí)主要訪問讀寫的是工作內(nèi)存。
線程、主內(nèi)存、工作內(nèi)存三者的交互關(guān)系
線程、主內(nèi)存、工作內(nèi)存三者的交互關(guān)系

12.2. 內(nèi)存間的相互操作

  • 一個(gè)變量如何從主內(nèi)存copy到工作內(nèi)存
  • 如何從工作內(nèi)存同步回主內(nèi)存。
  • Java內(nèi)存模型中定義了以下8種操作來完成主內(nèi)存和工作內(nèi)存之間交互的實(shí)現(xiàn)細(xì)節(jié):
    • lock: 作用于主內(nèi)存的變量,它把一個(gè)變量標(biāo)示為一條線程獨(dú)占的狀態(tài)。
    • unlock:作用于主內(nèi)存的變量,它把一個(gè)處于lock狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定。
    • read:作用于住內(nèi)存的變量,它把一個(gè)變量的值從主內(nèi)存?zhèn)鬏數(shù)焦ぷ鲀?nèi)存中,以便隨后的load動(dòng)作使用。
    • load:作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入到工作內(nèi)存的變量副本中。
    • use:作用于工作內(nèi)存的變量,它把工作內(nèi)存中的一個(gè)變量的值傳遞給執(zhí)行引擎,每當(dāng)虛擬機(jī)遇到一個(gè)需要使用變量值的字節(jié)碼的指令時(shí)會(huì)執(zhí)行這個(gè)操作。
    • assign:作用于工作內(nèi)存的變量,它把過一個(gè)執(zhí)行引擎接受到的值賦值給工作內(nèi)存的變量,每當(dāng)虛擬機(jī)遇到一個(gè)給變量復(fù)制的字節(jié)碼指令時(shí)執(zhí)行這個(gè)操作。
    • store:作用于工作內(nèi)存的變量,它把工作內(nèi)存中的一個(gè)變量的值傳遞到主內(nèi)存中,以便隨后的write操作。
    • wirte:作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中得到的變量值放到主內(nèi)存的變量中。
    • 8中基本操作需要滿足以下規(guī)則:


      image_1b5ucg6rn1oha4a8mp9piv3v69.png-150.6kB
      image_1b5ucg6rn1oha4a8mp9piv3v69.png-150.6kB

12.3.volatile型變量的特殊規(guī)則

1,當(dāng)一個(gè)變量的定義為volatile變量之后,此變量對(duì)所有線程是可見的。
    - 基于volatile變量的運(yùn)算在并發(fā)下是安全的???
    java里面的運(yùn)算并非原子操作,所以volatile變量在并發(fā)條件下也是不安全的。
2. 禁止指令重排序優(yōu)化。

12.4.先行發(fā)生原則(happen-before原則)

13.線程安全與鎖優(yōu)化


問題

  1. PSYoungGen/PSOldGen/PSPermGen區(qū)別

    PS是Paraller Scavenge的簡(jiǎn)稱。
    PSYoungGen:新生代
    PSOldGen:老年代
    PSPermGen:永久代

    • SUN JVM GC 使用是分代收集算法,即將內(nèi)存分為幾個(gè)區(qū)域,將不同生命周期的對(duì)象放在不同區(qū)域里.
      新的對(duì)象會(huì)先生成在Young area,也就是PSYoungGen中
      在幾次GC以后,如過沒有收集到,就會(huì)逐漸升級(jí)到PSOldGen 及Tenured area(也就是PSPermGen)中。
    • 在GC收集的時(shí)候,頻繁收集生命周期短的區(qū)域(Young area),因?yàn)檫@個(gè)區(qū)域內(nèi)的對(duì)象生命周期比較短,GC 效率也會(huì)比較高。而比較少的收集生命周期比較長(zhǎng)的區(qū)域(Old area or Tenured area),以及基本不收集的永久區(qū)(Perm area)。

參考

  1. Java 內(nèi)存模型及GC原理
  2. java 內(nèi)存垃圾回收模型
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,476評(píng)論 1 34
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器,...
    加油小杜閱讀 1,588評(píng)論 1 15
  • 1.運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域,這些區(qū)域...
    adison閱讀 2,538評(píng)論 1 43
  • 1、數(shù)據(jù)庫(kù)事務(wù)的特性 1、原子性(Actiomic):指整個(gè)數(shù)據(jù)庫(kù)事務(wù)不可分割的工作單位;2、一致性(Consis...
    aa2c98198994閱讀 406評(píng)論 1 1
  • 你在害怕什么? 夜晚那么黑 你為什么要帶上面具? 它遮不住你的內(nèi)心 一切都變了 沒有人會(huì)記得你 只能怪你自己 面具...
    無盡De華爾茲閱讀 151評(píng)論 0 0

友情鏈接更多精彩內(nèi)容