jvm内存模型_JVM内存模型的相关概念
1.前言
Android的虛擬機是根據移動設備的特點基于Java虛擬機(JVM)改進而來,雖然沒有保留規范,但作為Java語言的使用者,了解一下JVM的規范還是有必要的。
2.JVM內存模型
JVM在執行Java程序時,會把它管理的內存劃分為若干個的區域,每個區域都有自己的用途和創建銷毀時間。如下圖所示,可以分為兩大部分,線程私有區和共享區:
Memory.png
2.1.線程私有區
程序計數器。當同時進行的線程數超過CPU數或其內核數時,就要通過時間片輪詢分派CPU的時間資源,不免發生線程切換。這時,每個線程就需要一個屬于自己的計數器來記錄下一條要運行的指令。如果將是Java方法,則記錄執行的字節碼地址;是本地方法,則計數器為空。
虛擬機棧,與線程同時創建。每個方法執行時都會創建一個棧幀來存儲方法的信息,新調用的方法入棧,返回的出棧,所以棧的大小決定方法調用的可達深度。若需要的棧深度大于可用深度時,則StackOverflowError;若棧進行擴展,但內存不夠時,OutOfMemoryError。
本地方法棧,與虛擬機棧作用相似。但它不是為Java方法服務的,而是本地方法(C語言)。由于規范對這塊沒有強制要求,不同虛擬機實現方法不同。
2.2.線程共享區
此區域是用來存儲被各線程共享的數據的。
方法區,用于存放加載類的元數據信息,如常量、靜態變量和即時編譯器編譯后的代碼。若要分代,算是永久代,以前類大多“static”的,很少被卸載或收集,現回收廢棄常量和無用的類。其中運行時常量池存放編譯生成的各種常量。
堆,存放對象實例和數組,是垃圾回收的主要區域,分為新生代和老年代。剛創建的對象在新生代的Eden區中,經過GC后進入新生代的S0區中,再經過GC進入新生代的S1區中,15次GC后仍存在就進入老年代。這是按照一種回收機制進行劃分的,不是固定的。若堆的空間不夠實例分配,則OutOfMemoryError。
2.3.注意事項
棧是運行時單位,代表著邏輯,內含基本數據類型和堆中對象引用,所在區域連續,沒有碎片;堆是存儲單位,代表著數據,可被多個棧共享(包括成員中基本數據類型、引用和引用對象),所在區域不連續,會有碎片。
3.垃圾回收
我們都知道調用 System.gc() 方法只是通知系統去回收,是否回收不能確定。
3.1.回收的判斷
JVM中,將一個對象真正回收需經歷兩次標記過程,每次都是先判斷對象有沒有被持有引用,再判斷對象是否必要執行 finalize() 方法。
持有判斷。最先使用是引用計數算法,當對象有一個引用,即增加一個計數;刪除一個引用,即減少一個計數。計數為零的對象,判斷為不可用,但是無法處理循環引用的問題。現主流的都是可達性分析算法,通過將一系列稱為GC Roots的對象作為起始點,開始向下搜索,走過的路徑則是引用鏈。若所有GC Roots都與某對象無引用鏈相連,即不可達時,判斷為不可用。
注意:GC Roots對象包括:虛擬機棧(棧幀中的本地變量表)中引用對象;方法區中類靜態屬性引用的對象;方法區中常量池引用的對象;本地方法棧(一般的本地方法,即JNI)中引用的對象。必要判斷。當對象沒有重寫 finalize() 方法或者 finalize() 方法已被虛擬機調用過,都將視為“沒有必要執行”。否則此對象將放置在F-Queue的隊列中,由一個虛擬機自動建立的、低優先級的Finalizer線程去觸發該方法,但不承諾等待它運行結束,以防執行緩慢或為死循環,導致隊列其它對象永久等待,乃至內存回收系統崩潰。
對F-Queue中對象進行二次標記。只要有對象重新與GC Roots對象關聯,就會被移出隊列,否則GC回收。
3.2.垃圾收集算法
當確定哪些垃圾可以被回收后,需要做的就是高效地進行垃圾回收。由于JVM沒有給出明確的規定,各廠商實現方式不同,這里只討論常見垃圾收集算法的核心思想。
標記-清除算法,最基礎的算法,分為兩個階段。標記階段:標出所有需要被回收的對象;清除階段:回收被標記對象所占用的空間。但容易產生大量內存碎片,導致無足夠空間分配給大對象,從而提前觸發垃圾收集動作。
復制算法,為了解決標記-清除算法的缺陷。將可用內存按容量分為大小相等的兩塊,每次只使用其中的一塊。當一塊用完時,復制可用對象至另一塊并清除自己的內存空間,從而避免出現內存碎片。但可用內存為實際的一半,利用率低;且當存活對象很多時,效率也會降低。
標記-整理算法,吸取以上兩種算法優點。標記階段與標記-清除算法同階段一致,整理階段則將存活對象移向一端,再清理邊界以外空間。
分代收集算法,目前主流。根據對象存活的生命周期,將內存劃分為兩大區域。老年代:每次垃圾收集只有少量對象需回收,一般采用標記-整理算法;新生代:每次垃圾收集都有大量對象需回收,大部分采用復制算法。但空間上不是等大的兩塊,而是一塊大的Eden區域,兩塊小的Survivor區域,每次只使用一大一小兩區域。垃圾回收時,它們將內部存活對象都移至空閑的小區域并清理自己。
3.3.垃圾收集器
垃圾收集算法是理論,而垃圾收集器是實現。下面根據海子的文章列出HotSpot(JDK 7)提供的幾種垃圾收集器。
Serial/Serial Old 收集器是最基本最古老的收集器,它是一個單線程收集器,并且在它進行垃圾收集時,必須暫停所有用戶線程。Serial收集器是針對新生代的收集器,采用的是Copying算法;Serial Old收集器是針對老年代的收集器,采用的是Mark-Compact算法。它的優點是實現簡單高效,但是缺點是會給用戶帶來停頓。
ParNew 收集器是Serial收集器的多線程版本,使用多個線程進行垃圾收集。
Parallel Scavenge/Parallel Old 收集器是多線程(并行)收集器。Parallel Scavenge收集器是針對新生代的收集器,它在回收期間不需要暫停其他用戶線程,其采用的是Copying算法,該收集器與前兩個收集器有所不同,它主要是為了達到一個可控的吞吐量;Parallel Old收集器是針對老年代的收集器,使用多線程和Mark-Compact算法。
CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種并發收集器,采用的是Mark-Sweep算法。
G1收集器是當今收集器技術發展最前沿的成果,它是一款面向服務端應用的收集器,它能充分利用多CPU、多核環境。因此它是一款并行與并發收集器,并且它能建立可預測的停頓時間模型。
4.內存分配
內存分配主要是在堆上分配,由于涉及到分配時某區域空間不足等問題,需結合垃圾收集器和JVM相關參數,所以規則不是固定的。
5.總結
到這里,基本上可以在寫代碼時大致知道對象的內存情況,所以一定要注意避免內存泄露及其導致的內存溢出問題。
總結
以上是生活随笔為你收集整理的jvm内存模型_JVM内存模型的相关概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android so abi适配,And
- 下一篇: 企业办公自动化系统_OA系统的核心功能有