JVM相關(guān)總結(jié)

[JVM]

雖然大部分情況下不需要我們直接對Java內(nèi)存方面進(jìn)行直接操作螺垢,但是了解其中的原理和調(diào)優(yōu)還是比較重要的蠢护,JVM中的總結(jié)如下:

[運(yùn)行數(shù)據(jù)區(qū)]

  1. 程序計(jì)數(shù)器
    每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器蹄皱,是線程私有的等孵。
    若是正在運(yùn)行一個(gè)方法辈赋,計(jì)數(shù)器記錄正在執(zhí)行虛擬機(jī)字節(jié)碼指令地址袋哼;
    執(zhí)行的是native的方法纹安,計(jì)數(shù)器為空(Undefined)尤辱,不存在OutOfMemoryError

  2. 虛擬機(jī)棧
    線程私有,java方法執(zhí)行的內(nèi)存模型厢岂。
    每個(gè)方法運(yùn)行的時(shí)候會創(chuàng)建一個(gè)棧幀光督,
    棧幀存儲著 ->
    (a)局部變量
    用于存放方法參數(shù)和方法內(nèi)部定義的局部變量
    包括基本數(shù)據(jù)類型boolean,byte,char,int,short,double,long.float,對象引用類型reference->不等于對象本身,returnAddress
    (b)操作數(shù)棧
    后入先出
    (c)動態(tài)鏈接
    (d)方法返回地址
    返回方法被調(diào)用的位置
    (e)一些額外的附加信息
    規(guī)范里沒有提到的信息,例如與調(diào)試相關(guān)的信息

  3. 本地方法棧
    線程私有塔粒;
    虛擬機(jī)使用的native的方法服務(wù)结借。

  4. java堆
    java堆是被所以線程共享的一塊內(nèi)存區(qū)域,啟動時(shí)候創(chuàng)建卒茬。
    所有對象實(shí)例和數(shù)據(jù)在堆上分配內(nèi)存船老。

  5. 方法區(qū)
    各個(gè)線程共享的內(nèi)存區(qū)域;
    存儲java虛擬機(jī)加載的類信息,訪問修飾符圃酵,方法描述柳畔,常量,靜態(tài)變量郭赐,編譯后的代碼等數(shù)據(jù)薪韩。
    (a)運(yùn)行的常量池
    class文件->動態(tài)性
    (b)直接內(nèi)存
    例如NIO基于通道和緩沖區(qū)的I/O方式調(diào)用native

[垃圾回收]

  1. 引用計(jì)數(shù)算法
    對象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用時(shí)候捌锭,計(jì)數(shù)器加1俘陷;引用失效時(shí),計(jì)數(shù)器值減1观谦;任何時(shí)候計(jì)數(shù)器的值為0拉盾,對象不再使用。
  2. 可達(dá)性分析算法
    以GC Roots對象為起始點(diǎn)豁状,當(dāng)一個(gè)對象到達(dá)GCRoots沒有任何引用鏈的時(shí)候捉偏,證明對象不可達(dá)倒得。
    作為GCRoots對象的包括:
(a) 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象  
(b) 方法區(qū)中類靜態(tài)屬性引用的對象  
(c) 方法區(qū)中常量引用的對象  
(d) 本地方法棧中JNI(即一般說的native方法)引用的對象
  1. 標(biāo)記-清除算法
  2. 復(fù)制算法
    內(nèi)存分為一塊較大的Eden和兩塊較小的Survivor空間,每次使用Eden和一塊Survivor空間夭禽;
    回收時(shí)屎暇,將Eden和Survivor存活的對象一次性復(fù)制到另外一塊Survivor空間,清理用過的Eden和Survivor空間,默認(rèn)Eden和Survivor大小比例8:1
  3. 標(biāo)記-整理算法

[垃圾收集器]

  1. Serial收集器
    新生代采取復(fù)制算法驻粟,暫停所有用戶線程;
    老年代采取標(biāo)記整理算法凶异,暫停用戶所以線程
  2. ParNew收集器
    Serial收集器的多線程版本
    GC多線程蜀撑,新生代采取復(fù)制算法,暫停所有用戶線程剩彬;
    老年代采取標(biāo)記整理算法酷麦,暫停用戶所以線程
  3. Parallel Scavenge收集器
    CMS收集器盡可能縮短垃圾收集時(shí)用戶線程的停頓時(shí)間
    Parallel Scavenge收集器目的達(dá)到一個(gè)可控制的吞吐量(吞吐量=運(yùn)行代碼時(shí)間/(運(yùn)行代碼時(shí)間+垃圾收集時(shí)間))
  4. Serial Old收集器
  5. Parallel Old收集器
  6. CMS收集器
    以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。
    采取標(biāo)記-清除算法 ->
(1)初始標(biāo)記
(2)并發(fā)標(biāo)記
(3)重新標(biāo)記
(4)并發(fā)清除
  1. G1收集器
    面向服務(wù)端應(yīng)用的垃圾收集器
    步驟 ->
(a)初始標(biāo)記
(b)并發(fā)標(biāo)記
(c)最終標(biāo)記
(d)篩選回收

[內(nèi)存分配]

-Xms20M,-Xmx20M,-Xmn10M -XX:SurvivorRatio=8,-XX:+PrintGCDetails
java堆大小為20M喉恋,不可擴(kuò)展沃饶,10M分配新生代,10M分配老年代
新生代的Eden區(qū)與一個(gè)Survivor區(qū)的空間比例為8:1
新生代的總可用空間(Eden區(qū)+1個(gè)Survivor區(qū)的總?cè)萘?
-XX:PermSize永久代
-XX:MaxPermSize永久代最大容量

存儲的是java的類信息轻黑,包括解析得到的方法糊肤、屬性、字段等等氓鄙。永久帶基本不參與垃圾回收馆揉。
在jdk1.8之前,通過-XX:PermSize=64m -XX:MaxPermSize=128m來調(diào)整永久代大小抖拦,
在jdk1.8之后升酣,永久代被移除,原本存儲在永久代的數(shù)據(jù)將存放在一個(gè)叫做元空間的本地內(nèi)存區(qū)域态罪,
通過 -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m來調(diào)整元空間大小

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

生命周期
-> 加載

(a)通過一個(gè)類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流   
(b)將這個(gè)字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu)  
(c)在內(nèi)存中生成一個(gè)代表這個(gè)類的java.lang.Class對象噩茄,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口

-> 驗(yàn)證

(a)文件格式驗(yàn)證  
(b)元數(shù)據(jù)驗(yàn)證  
(c)字節(jié)碼驗(yàn)證  
(d)符號引用驗(yàn)證

-> 準(zhǔn)備 -> 解析 -> 初始化 -> 使用 -> 卸載

[類加載器]

  1. 啟動類加載器(Bootstrap ClassLoader)
    負(fù)責(zé)將存放<JAVA_HOME>\lib目錄中;
    被-Xbootclasspath參數(shù)指定的路徑中(僅按照文件名識別复颈,如rt.jar)
  2. 擴(kuò)展類加載器(Extension ClassLoader)
    負(fù)責(zé)加載<JAVA_HOME>\lib\ext目錄中
    或者被java.ext.dirs系統(tǒng)變量所指定的路徑中所有的類庫
  3. 應(yīng)用類加載器(Application ClassLoader)
    負(fù)責(zé)加載用戶類路徑ClassPath上所指定的類庫
  4. 自定義類加載器 UserClassLoader

如果一個(gè)類加載器收到了類加載的請求绩聘,請求委派給父類加載器,只有當(dāng)父類反饋無法完成券膀,子類嘗試加載君纫。

[Java內(nèi)存模型]

Java內(nèi)存模型的主要目標(biāo)是定義程序中各個(gè)變量的訪問規(guī)則,即在虛擬機(jī)中將變量存儲到內(nèi)存和從內(nèi)存中取出變量這樣的底層細(xì)節(jié)芹彬。
主內(nèi)存主要對應(yīng)與java堆里的對象實(shí)例數(shù)據(jù)部分蓄髓,而工作內(nèi)存則對應(yīng)虛擬機(jī)棧中的部分區(qū)域。
內(nèi)存間的交互

  1. lock鎖定
    作用于主內(nèi)存的變量舒帮,它把一個(gè)變量標(biāo)識為一條線程獨(dú)占的狀態(tài)会喝。
  2. unlock(解鎖)
    作用于主內(nèi)存的變量陡叠,把一個(gè)處于鎖定狀態(tài)的變量釋放出來,釋放后才能被其他線程鎖定肢执。
  3. read(讀取)
    作用于主內(nèi)存的變量枉阵,將一個(gè)變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存,以便隨后的load動作使用预茄。
  4. load(載入)
    作用于工作內(nèi)存的變量兴溜,它把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中。
  5. use(使用)
    作用于工作內(nèi)存的變量耻陕,它把一個(gè)變量的值傳遞給執(zhí)行引擎拙徽,每當(dāng)虛擬機(jī)遇到需要使用變量的值的字節(jié)碼指令時(shí)將會執(zhí)行這個(gè)操作。
  6. assign(賦值)
    作用于工作內(nèi)存的變量诗宣,它把執(zhí)行引擎接收到的值賦給工作內(nèi)存的變量膘怕,每當(dāng)虛擬機(jī)遇到一個(gè)給變量賦值的字節(jié)碼指令時(shí)執(zhí)行這個(gè)操作。
  7. store
    作用于工作內(nèi)存的變量召庞,它把工作內(nèi)存內(nèi)存中一個(gè)變量的值傳送給主內(nèi)存中岛心,以便隨后的write操作使用。
  8. write(寫入)
    作用于主內(nèi)存的變量篮灼,它把從store操作從工作內(nèi)存中得到的變量的值放入主內(nèi)存的變量中忘古。

volatile

  1. 此變量對所以線程可見(等線程A寫進(jìn)主內(nèi)存結(jié)束,線程B才開始讀取)
  2. 主內(nèi)存一致诅诱,工作內(nèi)存不能保持一致
  3. 禁止指令重排序優(yōu)化

內(nèi)存模型特征

  1. 原子性
  2. 可見性
    變量修改后將新值同步回主內(nèi)存存皂,在變量讀取前從主內(nèi)存刷新變量值這種依賴主內(nèi)存作為傳遞媒介的方式來實(shí)現(xiàn)可見性。
    volatile的特殊規(guī)則保證了新值能立即同步到主內(nèi)存逢艘,以及每次使用前立即從主內(nèi)存刷新旦袋。
  3. 有序性

[線程的實(shí)現(xiàn)]

  1. 使用內(nèi)核線程實(shí)現(xiàn)
    內(nèi)核通過操縱調(diào)度器對線程進(jìn)行調(diào)度,并將線程的任務(wù)映射到各個(gè)處理器上它改。
    內(nèi)核線程一種高級接口--輕量級進(jìn)程LWP疤孕,每個(gè)輕量級進(jìn)程由一個(gè)內(nèi)核線程支持。
    用戶態(tài)和內(nèi)核態(tài)中來回切換央拖。
    1:1
  2. 使用用戶線程實(shí)現(xiàn)
    1:N
  3. 使用用戶線程實(shí)現(xiàn)和使用用戶線程加輕量級進(jìn)程混合實(shí)現(xiàn)
    N:M

[線程安全的同步方法]

  1. 互斥同步
    互斥是實(shí)現(xiàn)同步的一種手段祭阀,臨界區(qū),互斥量鲜戒,信號量
    阻塞同步
  2. 非阻塞同步
(a)測試并設(shè)置
(b)獲取并增加
(c)交換
(d)比較并交換
(e)加載鏈接/條件存儲
  1. 無同步方案
    不涉及共享數(shù)據(jù)专控,不依賴堆的數(shù)據(jù)和公共系統(tǒng)資源

[鎖優(yōu)化]

  1. 自旋鎖和自適應(yīng)自旋
    自旋--線程執(zhí)行一個(gè)忙循環(huán)-XX:+UseSpinning參數(shù)來開啟
    自旋超過一定次數(shù)沒有成功獲得鎖,便使用傳統(tǒng)方式掛起線程,自旋次數(shù)默認(rèn)是10次遏餐,用戶可以使用參數(shù) -XX:PreBlockSpin更改
  2. 自適應(yīng)的自旋
    由前一次在同一個(gè)鎖上的自旋時(shí)間時(shí)間及鎖的擁有者的狀態(tài)來決定,
    如果同一個(gè)鎖對象伦腐,自旋剛剛成功過,允許自旋更長時(shí)間失都,很少成功柏蘑,則省略自旋這個(gè)過程幸冻。
  3. 鎖消除
    虛擬機(jī)及時(shí)編譯器運(yùn)行的時(shí)候,對一些代碼要求同步咳焚,但是不可能存在數(shù)據(jù)競爭的進(jìn)行消除洽损。
  4. 鎖粗化
    虛擬機(jī)探測到一串零碎的操作對同一個(gè)對象枷鎖,會把加鎖同步到整個(gè)操作序列外部革半。
  5. 輕量級鎖
    無競爭的情況下使用CAS操作去消除同步使用的互斥量
  6. 偏向鎖
    無競爭的情況下把整個(gè)同步都消除掉碑定,CAS操作不進(jìn)行。
    -XX:+UseBiasedLocking
    鎖對象第一次被線程獲取又官,會把對象頭標(biāo)志設(shè)置為“01”不傅,即偏向模式,同時(shí)用CAS操作記錄在對象的Mark Word之中赏胚,
    如果CAS成功,以后每次持有偏向鎖的線程都不再進(jìn)行任何同步操作商虐。
    如果有另一個(gè)線程來獲取觉阅,偏向鎖結(jié)束,根據(jù)鎖對象是否處于被鎖定的狀態(tài)秘车,撤銷偏向典勇,后續(xù)操作和輕量級鎖執(zhí)行類似。
    缺點(diǎn):多個(gè)線程下訪問叮趴,并不適合割笙。

本文參考于《深入理解Java虛擬機(jī)》推薦大家看一看,會對自己收獲很大眯亦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伤溉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子妻率,更是在濱河造成了極大的恐慌乱顾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宫静,死亡現(xiàn)場離奇詭異走净,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)孤里,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門伏伯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捌袜,你說我怎么就攤上這事说搅。” “怎么了虏等?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵蜓堕,是天一觀的道長抛虏。 經(jīng)常有香客問我,道長套才,這世上最難降的妖魔是什么迂猴? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮背伴,結(jié)果婚禮上沸毁,老公的妹妹穿的比我還像新娘。我一直安慰自己傻寂,他們只是感情好息尺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疾掰,像睡著了一般搂誉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上静檬,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天炭懊,我揣著相機(jī)與錄音,去河邊找鬼拂檩。 笑死侮腹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的稻励。 我是一名探鬼主播父阻,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼望抽!你這毒婦竟也來了加矛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤煤篙,失蹤者是張志新(化名)和其女友劉穎荒椭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舰蟆,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡趣惠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了身害。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片味悄。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖塌鸯,靈堂內(nèi)的尸體忽然破棺而出侍瑟,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布涨颜,位于F島的核電站费韭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏庭瑰。R本人自食惡果不足惜星持,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弹灭。 院中可真熱鬧督暂,春花似錦、人聲如沸穷吮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捡鱼。三九已至八回,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驾诈,已是汗流浹背缠诅。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翘鸭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓戳葵,卻偏偏與公主長得像就乓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子拱烁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java8張圖 11生蚁、字符串不變性 12、equals()方法戏自、hashCode()方法的區(qū)別 13邦投、...
    Miley_MOJIE閱讀 3,707評論 0 11
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司擅笔,掛了不少志衣,但最終還是拿到小米、百度猛们、阿里念脯、京東、新浪弯淘、CVTE绿店、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,253評論 11 349
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧假勿、本地方法棧借嗽、堆、程序計(jì)數(shù)器转培,...
    加油小杜閱讀 1,519評論 1 15
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理恶导,因此不免有一些不準(zhǔn)確的地方,同時(shí)不同JDK版本的...
    高廣超閱讀 15,608評論 3 83
  • 既是來學(xué)習(xí)的堡距,就先從自然拼讀法說起甲锡。 什么是自然拼讀法? 先用自己的話來解釋一下:26個(gè)字母除了我們所熟知的字母名...
    SophieXiong閱讀 532評論 0 1