JVM學習總結

來源:互聯網
上載者:User

標籤:

什麼是JVM

  JVM包含三個層面,抽象規範,利用該規範來定義一個虛擬電腦,該虛擬電腦有自己的指令集,一個具體的實現,根據抽象規範,針對不同的硬體平台,已經實現的一個虛擬機器,一個正在啟動並執行虛擬機器的執行個體,實現虛擬機器後,要想使用虛擬機器,首先要建立一個虛擬機器的執行個體,然後將該虛擬機器的執行個體載入到記憶體運行,一個java應用程式對應一個虛擬機器的執行個體,一個虛擬機器的執行個體僅為一個java應用程式服務。
  JVM的執行個體的生命週期,隨著應用程式的啟動而開始,隨著應用程式的結束而結束,虛擬機器的執行個體使用系統建立的進程的資源,運行在系統為該進程建立的核心級線程中,應用程式運行在虛擬機器建立的使用者級線程中,JVM中的線程分使用者級線程和守護線程,初始使用者級線程只有一個,為應用程式中的main方法對應的主線程,守護線程通常由JVM使用,如記憶體回收線程,守護線程的特點是當所有的使用者級線程結束後,無論守護線程的語句是否執行完都會隨之結束,JVM可以將一個使用者級線程標記為守護線程。

JVM的記憶體配置

  java的記憶體配置指的是JVM的記憶體配置,也稱為JVM運行時資料區,首先在實體記憶體中劃分出一塊地區,而後在該地區內載入運行一個且僅一個JVM的執行個體,JVM的執行個體會從該地區內類比出PC寄存器,棧,堆,方法區,資料區段,程式碼片段。
  PC寄存器為JVM執行個體的每個使用者級線程專屬的記憶體,用於記錄該線程要執行的下一條指令的的地址,速度快。
  棧為JVM執行個體的每個使用者級線程專屬的記憶體,其成員是由一個個的棧幀組成,棧幀用於存放該線程正在執行的java方法的執行狀態,包括局部的基礎資料型別 (Elementary Data Type)變數,局部的參考型別變數,方法的參數,傳回值,運算的中間結果,對於通過JNI調用的java本地方法,暫時認為棧幀僅存放一個指向本地方法棧的引用,速度快。
  參考型別變數的值為一個long型值,JVM的棧是向下生長的,即向低地址擴充,JVM沒有資料寄存器,指令集運算的中間結果均以棧幀的形式存放線上程的棧中,棧幀包含著線程執行的一個方法的全部執行狀態,由此線程每執行一個方法,就是建立一個對應該方法的棧幀並壓入棧,方法執行結束後,將該方法的棧幀彈出棧,本地方法的棧幀僅存放一個指向本地方法棧的引用,本地方法的執行狀態被儲存在本地方法棧中,本地方法棧實際已經跳出JVM,與具體的平台有關,多線程在對各自的棧成員訪問時不存在同步問題,棧使用享元模式來存放棧成員。
  例如,int a = 3,int b = 3,a = 4,執行第一條語句,查詢該線程的棧記憶體中是否有3,沒有則開闢一個棧空間並存入3,同時讓a指向該棧空間,執行第二條語句,查詢棧空間中是否有3,有則直接讓b指向該棧空間,執行第三條語句,查詢棧空間是否有4,沒有則開闢一個棧空間並存入4,同時讓a指向該棧空間,由此a值的改變不是直接修改a所指向的棧空間的內容,而是重新指向另一個棧空間。
  堆為JVM所屬的核心級線程所有的,可以被該JVM的執行個體的所有使用者級線程共用,多線程對堆成員的訪問存在同步問題,速度沒有棧快,分實體區和常量池。
  實體區存放參考型別變數指向的實體,無論是局部參考型別的變數還是成員參考型別的變數,它們指向的實體都存放在堆的實體區包括數組的實體,實體區僅存放對象實體的成員基礎資料型別 (Elementary Data Type)的變數和成員參考型別的變數,不包括成員參考型別變數指向的實體和成員方法,個人認為,應該有指向方法區方法的引用。
  常量池存放類,介面,方法的標識符聲明,局部常量,成員常量,使用享元模式。
  方法區為JVM所屬的核心級線程所有,可以被該JVM的執行個體的所有使用者級線程共用,僅存放實體的成員方法,不存放資料,速度沒有棧快。
  資料區段為JVM所屬的核心級線程所有,可以被該JVM的執行個體的所有使用者級線程共用,存在同步問題,存放類的靜態屬性,速度沒有棧快。
  程式碼片段為JVM所屬的核心級線程所有,可以被該JVM的執行個體的所有使用者級線程共用,程式碼片段僅存放原始碼,不存放資料,速度沒有棧快。

JVM的常量池

  java的基礎資料型別 (Elementary Data Type)封裝類Byte,Short,Integer,Long,Float,Double,Character,Boolean中,除了Float與Double,其餘類型對-128—127之間的資料均使用常量池。

//s1與s2指向同一個空間,引用相同。String s1 = “how are you”String s2 = “how are you”//s3,s4指向不同的實體區,引用不同。String s3 = new String(“how are you”)String s4 = new String(“how are you”)//記憶體中建立了兩個對象實體,首先JVM檢查常量池是否有“abc”,沒有開闢空//間存入abc,之後在實體區開闢空間存abc。String s5 = new String(“abc”)//記憶體中建立了三個對象實體,均在常量池中String s6 = “abc” + “d”//記憶體中建立了七個對象實體,均在常量池中,為//a,b,c,d,ab,abc,abcd,+會額外的產生對象,若用StringBuilder//的append則不會產生額外的對象。String s7 = “a” + “b” + “c” + “d”public class Test {    //成員基礎資料型別 (Elementary Data Type)變數i的值3存放在實體區    public int i = 3;    //成員參考型別變數a的值存放在實體區,a指向的實體開闢自己的實    //體區存放    public A a = new A();    //成員參考型別變數itg1的值存放在實體區,3在常量池    public Integer itg1 = 3;    //成員引用變數itg2的值存放在實體區,itg2指向的實體開闢自己    //的實體區存放3    public Integer itg2 = new Integer(3);    //成員參考型別變數itg3的值存放在實體區,由於128在-128—127    //之外,itg3指向的實體使用自動類型封裝,開闢自己的實體區存放    //128    public Integer itg3 = 128;    public void Test() {        //局部基礎資料型別 (Elementary Data Type)變數i的值3存放在棧內         int i = 3;        //局部參考型別變數a的值存放在棧內,a指向的實體開闢        //自己的實體區存放        A a = new A();        //局部參考型別變數s1的值存放在棧內,字串常量how        //are you在常量池        String s1 = "how are you";        //局部參考型別變數itg1的值存放在棧內,3使用常量池        Integer itg1 = 3;    }}
JVM的記憶體回收

  JVM的記憶體回收行程每隔一段時間,如JVM空閑時,動態回收那些無任何對象引用的對象實體所佔用的堆記憶體空間,可通過System.gc()或Runtime.getRuntime().gc()來顯示地通知JVM進行一次記憶體回收,但是通知歸通知,JVM到底什麼時候收都不一定,我們無法控制,由JVM自己決定,JVM有七種記憶體回收行程。
  引用計數收集器,指實體區的每一個對象實體都維持一個引用計數器,用於記錄指向該對象實體的引用的個數,當一個對象實體的引用計數器的值為0的時候,該對象實體可以被當作記憶體回收,同時該對象內部引用的任何對象實體的引用計數器的值會相應地減一,由此該方法中一個對象的回收可能會導致其它對象的回收行動。
  好處是,引用計數器嵌入在程式中和程式一起運行,可即時判斷引用計數器的值,快速收集,適用於即時環境。
  壞處是,引用計數的增減會帶來額外的開銷且無法處理循環參考,如有兩個對象a,b分別引用實體A,B,實體A中用對象b’引用了實體B,實體B中用對象a’引用了實體A,此時實體A的引用計數為2,分別為a引用與B中a’引用,實體B的引用計數為2,分別為b引用與A中b’引用,令a = null,實體A不會被收集,因為B中a’引用A,除非B被收集,而b = null,不會導致B被收集,因為A中b’引用未被賦空,而實體A和B此時已經不能由程式員控制。
  跟蹤收集器,分標記和清除兩個階段,標記階段會從引用樹的根對象開始遍曆,標記遇到的每一個對象實體,清除階段會釋放未被標記的對象實體。
  壓縮收集器,用於處理跟蹤收集器中產生的堆碎塊,將堆中未被收集的對象實體滑動到堆的一端,使另一端空出一個大的連續的空閑地區,對象實體移動後,對象實體的引用也要同時更新,使用一個中間控制代碼表,讓表中的記錄真正指向堆中的實體,引用指向表中的記錄,由此對象實體移動時,只需修改控制代碼表,無需修改對象的引用,java中不直接使用地址而是使用引用可能就是在此實現的。
  拷貝收集器,在遍曆引用樹的過程中,凡是被遍曆到的對象實體都被同時拷貝到一個新的地區且在新地區連續存放,這樣原地區的空閑片段,以及未被遍曆到的對象實體,都直接被視為空白閑地區,由此一次遍曆拷貝的過程就完成了標記與清除的全部過程同時還可以清除堆碎塊,此方法堆被分成兩個地區,任何時候只能使用一個地區,當一個地區的空間耗盡時,停止分配,執行拷貝操作,又叫停止並拷貝。
  壞處是,需要兩倍大小的實體區,因為一次只能使用一半的實體區。
按代收集器,將實體區分成若干子實體區,每個子實體區為一代,有一個年齡層,最年幼的一代子實體區中的對象被收集的頻率最高,這裡面存放的對象大多是生命週期很短的,他們被用完的機率大,自然被收集的機率大,該子實體區中的對象經過幾次收集後,未被收集的對象被認為是生命週期較長的對象,它們會被轉移到年長的一代子實體區中,該子實體區中的對象的生命週期大多較長,被執行記憶體回收的次數也會減少。
  自適應收集器,指根據上述幾種垃圾收集器的適應情境,自適應的調整JVM的垃圾收集器,以使JVM不只使用一種垃圾收集器,而是可以使用多種垃圾收集器。
  漸進式垃圾收集器,可以避免一次收集全部的垃圾導致時間過長,影響系統效能,甚至被使用者察覺到,一次只收集部分垃圾,保證每次收集垃圾的時間限定在一定的時限之內,通常通過使用按代垃圾收集器來實現。

JVM學習總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.