JVM內(nèi)存模型的相關(guān)概念

1.前言


Android的虛擬機是根據(jù)移動設(shè)備的特點基于Java虛擬機(JVM)改進而來,雖然沒有保留規(guī)范付翁,但作為Java語言的使用者简肴,了解一下JVM的規(guī)范還是有必要的。

2.JVM內(nèi)存模型


JVM在執(zhí)行Java程序時百侧,會把它管理的內(nèi)存劃分為若干個的區(qū)域砰识,每個區(qū)域都有自己的用途和創(chuàng)建銷毀時間。如下圖所示移层,可以分為兩大部分仍翰,線程私有區(qū)和共享區(qū):


Memory.png
2.1.線程私有區(qū)
  • 程序計數(shù)器。當同時進行的線程數(shù)超過CPU數(shù)或其內(nèi)核數(shù)時观话,就要通過時間片輪詢分派CPU的時間資源,不免發(fā)生線程切換越平。這時频蛔,每個線程就需要一個屬于自己的計數(shù)器來記錄下一條要運行的指令。如果將是Java方法秦叛,則記錄執(zhí)行的字節(jié)碼地址晦溪;是本地方法,則計數(shù)器為空挣跋。
  • 虛擬機棧三圆,與線程同時創(chuàng)建。每個方法執(zhí)行時都會創(chuàng)建一個棧幀來存儲方法的信息避咆,新調(diào)用的方法入棧舟肉,返回的出棧,所以棧的大小決定方法調(diào)用的可達深度查库。若需要的棧深度大于可用深度時路媚,則StackOverflowError;若棧進行擴展樊销,但內(nèi)存不夠時整慎,OutOfMemoryError脏款。
  • 本地方法棧,與虛擬機棧作用相似裤园。但它不是為Java方法服務(wù)的撤师,而是本地方法(C語言)。由于規(guī)范對這塊沒有強制要求拧揽,不同虛擬機實現(xiàn)方法不同丈氓。
2.2.線程共享區(qū)

此區(qū)域是用來存儲被各線程共享的數(shù)據(jù)的。

  • 方法區(qū)强法,用于存放加載類的元數(shù)據(jù)信息万俗,如常量、靜態(tài)變量和即時編譯器編譯后的代碼饮怯。若要分代闰歪,算是永久代,以前類大多“static”的蓖墅,很少被卸載或收集库倘,現(xiàn)回收廢棄常量和無用的類。其中運行時常量池存放編譯生成的各種常量论矾。
  • 堆教翩,存放對象實例和數(shù)組,是垃圾回收的主要區(qū)域贪壳,分為新生代和老年代饱亿。剛創(chuàng)建的對象在新生代的Eden區(qū)中,經(jīng)過GC后進入新生代的S0區(qū)中闰靴,再經(jīng)過GC進入新生代的S1區(qū)中彪笼,15次GC后仍存在就進入老年代。這是按照一種回收機制進行劃分的蚂且,不是固定的配猫。若堆的空間不夠?qū)嵗峙洌瑒tOutOfMemoryError杏死。
2.3.注意事項

棧是運行時單位泵肄,代表著邏輯淑翼,內(nèi)含基本數(shù)據(jù)類型和堆中對象引用腐巢,所在區(qū)域連續(xù),沒有碎片窒舟;堆是存儲單位系忙,代表著數(shù)據(jù),可被多個棧共享(包括成員中基本數(shù)據(jù)類型惠豺、引用和引用對象)银还,所在區(qū)域不連續(xù)风宁,會有碎片。

3.垃圾回收


我們都知道調(diào)用 System.gc() 方法只是通知系統(tǒng)去回收蛹疯,是否回收不能確定戒财。

3.1.回收的判斷

JVM中,將一個對象真正回收需經(jīng)歷兩次標記過程捺弦,每次都是先判斷對象有沒有被持有引用饮寞,再判斷對象是否必要執(zhí)行 finalize() 方法。

  • 持有判斷列吼。最先使用是引用計數(shù)算法幽崩,當對象有一個引用,即增加一個計數(shù)寞钥;刪除一個引用慌申,即減少一個計數(shù)。計數(shù)為零的對象理郑,判斷為不可用蹄溉,但是無法處理循環(huán)引用的問題。現(xiàn)主流的都是可達性分析算法您炉,通過將一系列稱為GC Roots的對象作為起始點柒爵,開始向下搜索,走過的路徑則是引用鏈赚爵。若所有GC Roots都與某對象無引用鏈相連棉胀,即不可達時,判斷為不可用囱晴。
    注意:GC Roots對象包括:虛擬機棧(棧幀中的本地變量表)中引用對象膏蚓;方法區(qū)中類靜態(tài)屬性引用的對象;方法區(qū)中常量池引用的對象畸写;本地方法棧(一般的本地方法,即JNI)中引用的對象氓扛。
  • 必要判斷枯芬。當對象沒有重寫 finalize() 方法或者 finalize() 方法已被虛擬機調(diào)用過,都將視為“沒有必要執(zhí)行”采郎。否則此對象將放置在F-Queue的隊列中千所,由一個虛擬機自動建立的、低優(yōu)先級的Finalizer線程去觸發(fā)該方法蒜埋,但不承諾等待它運行結(jié)束淫痰,以防執(zhí)行緩慢或為死循環(huán),導(dǎo)致隊列其它對象永久等待整份,乃至內(nèi)存回收系統(tǒng)崩潰待错。
  • 對F-Queue中對象進行二次標記籽孙。只要有對象重新與GC Roots對象關(guān)聯(lián),就會被移出隊列火俄,否則GC回收犯建。
3.2.垃圾收集算法

當確定哪些垃圾可以被回收后,需要做的就是高效地進行垃圾回收瓜客。由于JVM沒有給出明確的規(guī)定适瓦,各廠商實現(xiàn)方式不同,這里只討論常見垃圾收集算法的核心思想谱仪。

  • 標記-清除算法玻熙,最基礎(chǔ)的算法,分為兩個階段疯攒。標記階段:標出所有需要被回收的對象嗦随;清除階段:回收被標記對象所占用的空間。容易產(chǎn)生大量內(nèi)存碎片卸例,導(dǎo)致無足夠空間分配給大對象称杨,從而提前觸發(fā)垃圾收集動作。
  • 復(fù)制算法筷转,為了解決標記-清除算法的缺陷姑原。將可用內(nèi)存按容量分為大小相等的兩塊,每次只使用其中的一塊呜舒。當一塊用完時锭汛,復(fù)制可用對象至另一塊并清除自己的內(nèi)存空間,從而避免出現(xiàn)內(nèi)存碎片袭蝗。可用內(nèi)存為實際的一半唤殴,利用率低;且當存活對象很多時到腥,效率也會降低朵逝。
  • 標記-整理算法,吸取以上兩種算法優(yōu)點乡范。標記階段與標記-清除算法同階段一致,整理階段則將存活對象移向一端晋辆,再清理邊界以外空間渠脉。
  • 分代收集算法瓶佳,目前主流。根據(jù)對象存活的生命周期为朋,將內(nèi)存劃分為兩大區(qū)域埃儿。老年代:每次垃圾收集只有少量對象需回收童番,一般采用標記-整理算法威鹿;新生代:每次垃圾收集都有大量對象需回收剃斧,大部分采用復(fù)制算法。但空間上不是等大的兩塊忽你,而是一塊大的Eden區(qū)域幼东,兩塊小的Survivor區(qū)域,每次只使用一大一小兩區(qū)域科雳。垃圾回收時根蟹,它們將內(nèi)部存活對象都移至空閑的小區(qū)域并清理自己。
3.3.垃圾收集器

垃圾收集算法是理論糟秘,而垃圾收集器是實現(xiàn)简逮。下面根據(jù)海子的文章列出HotSpot(JDK 7)提供的幾種垃圾收集器。

  • Serial/Serial Old 收集器是最基本最古老的收集器尿赚,它是一個單線程收集器散庶,并且在它進行垃圾收集時,必須暫停所有用戶線程凌净。Serial收集器是針對新生代的收集器悲龟,采用的是Copying算法;Serial Old收集器是針對老年代的收集器冰寻,采用的是Mark-Compact算法须教。它的優(yōu)點是實現(xiàn)簡單高效,但是缺點是會給用戶帶來停頓斩芭。
  • ParNew 收集器是Serial收集器的多線程版本没卸,使用多個線程進行垃圾收集。
  • Parallel Scavenge/Parallel Old 收集器是多線程(并行)收集器秒旋。Parallel Scavenge收集器是針對新生代的收集器,它在回收期間不需要暫停其他用戶線程诀拭,其采用的是Copying算法迁筛,該收集器與前兩個收集器有所不同,它主要是為了達到一個可控的吞吐量;Parallel Old收集器是針對老年代的收集器细卧,使用多線程和Mark-Compact算法尉桩。
  • CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種并發(fā)收集器贪庙,采用的是Mark-Sweep算法蜘犁。
  • G1收集器是當今收集器技術(shù)發(fā)展最前沿的成果,它是一款面向服務(wù)端應(yīng)用的收集器止邮,它能充分利用多CPU这橙、多核環(huán)境。因此它是一款并行與并發(fā)收集器导披,并且它能建立可預(yù)測的停頓時間模型屈扎。

4.內(nèi)存分配


內(nèi)存分配主要是在堆上分配,由于涉及到分配時某區(qū)域空間不足等問題撩匕,需結(jié)合垃圾收集器和JVM相關(guān)參數(shù)鹰晨,所以規(guī)則不是固定的。

5.總結(jié)


到這里止毕,基本上可以在寫代碼時大致知道對象的內(nèi)存情況模蜡,所以一定要注意避免內(nèi)存泄露及其導(dǎo)致的內(nèi)存溢出問題。由于內(nèi)容較深扁凛,大家可以參考這個系列文章忍疾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市令漂,隨后出現(xiàn)的幾起案子膝昆,更是在濱河造成了極大的恐慌,老刑警劉巖叠必,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荚孵,死亡現(xiàn)場離奇詭異,居然都是意外死亡纬朝,警方通過查閱死者的電腦和手機收叶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來共苛,“玉大人判没,你說我怎么就攤上這事∮缇ィ” “怎么了澄峰?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辟犀。 經(jīng)常有香客問我俏竞,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任魂毁,我火速辦了婚禮玻佩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘席楚。我一直安慰自己咬崔,他們只是感情好,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布烦秩。 她就那樣靜靜地躺著垮斯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闻镶。 梳的紋絲不亂的頭發(fā)上甚脉,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機與錄音铆农,去河邊找鬼牺氨。 笑死,一個胖子當著我的面吹牛墩剖,可吹牛的內(nèi)容都是我干的猴凹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼岭皂,長吁一口氣:“原來是場噩夢啊……” “哼郊霎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起爷绘,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤书劝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后土至,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體购对,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年陶因,在試婚紗的時候發(fā)現(xiàn)自己被綠了骡苞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡楷扬,死狀恐怖解幽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烘苹,我是刑警寧澤躲株,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站镣衡,受9級特大地震影響徘溢,放射性物質(zhì)發(fā)生泄漏吞琐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一然爆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧黍图,春花似錦曾雕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揩环,卻和暖如春搔弄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丰滑。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工顾犹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人褒墨。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓炫刷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親郁妈。 傳聞我的和親對象是個殘疾皇子浑玛,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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

  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準確的地方噩咪,同時不同JDK版本的...
    高廣超閱讀 15,629評論 3 83
  • 1.什么是垃圾回收顾彰? 垃圾回收(Garbage Collection)是Java虛擬機(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,559評論 17 311
  • 1.一些概念 1.1.數(shù)據(jù)類型 Java虛擬機中,數(shù)據(jù)類型可以分為兩類:基本類型和引用類型胃碾≌窍恚基本類型的變量保存原始...
    落落落落大大方方閱讀 4,545評論 4 86
  • JVM內(nèi)存模型Java虛擬機(Java Virtual Machine=JVM)的內(nèi)存空間分為五個部分,分別是: ...
    光劍書架上的書閱讀 2,522評論 2 26
  • JVM架構(gòu) 當一個程序啟動之前书在,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū))灰伟,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,673評論 0 7