JVM自動內存管理學習筆記


對於使用 C、C++ 的程序員來說,在內存管理領域,他們既是擁有最高權力的皇帝又是從事最基礎工作的勞動人民——擁有每一個對象的“所有權”,又擔負着每一個對象生命開始到終結的維護責任。對於 Java 程序員來說,在虛擬機自動內存管理機制的幫助下,不再需要為每一個 new 操作去寫配對的 delete/free 代碼,不容易出現內存泄漏和內存溢出,看起一切都很美好。不過,也正因為 Java 程序員把控制內存的權力交給了 Java 虛擬機,一旦出現內存泄漏和溢出,如果不了解虛擬機是怎樣使用內存的,那排查錯誤將會成為一項異常艱難的工作。
 

一、Java虛擬機和Java內存區域概述

        1、虛擬機:
             定義:模擬某種計算機體系結構,執行特定指令集的軟件。
             分為系統虛擬機(Virtual Box、VMware),進程虛擬機
        2、進程虛擬機
              並不會完整的模擬一個操作系統的運行環境,僅僅是提供特定指令集的運行環境。如JVM、Adobe Flash Player、FC模擬器
        3、高級語言虛擬機
              把特定指令集的范圍限定為高級語言,如JVM、.NET CLR、P-Code(pascal)
        4、Java語言虛擬機
               可以執行Java語言的高級語言虛擬機,Java語言的虛擬機並不一定就可以成為JVM,譬如:Apache Harmony
        5、JavaTM虛擬機
               必須通過Java TCK(Technology Compatibility kit)的兼容性測試的Java語言虛擬機才能稱為“JavaTM虛擬機
               JavaTM虛擬機並非一定要執行“Java”程序,他跟Java語言並沒有嚴格相關,他跟java的編譯文件class文件產生關聯,即其他語言編譯的符合格式的class文件也可以運行
               業界三大商用JVM:
                  Oracle HotSpot:JDK中使用的虛擬機,命名來自它的“熱點代碼探測”技術、
                  Oracle JRockit VM:、 
                  IBM J9 VM:
         6、共有設計,私有實現
                  《Java虛擬機規范》定義了概念模型,但同時也聲明了這些概念不約束虛擬機的具體實現
         7、Java虛擬機運行時數據區
                   程序計數器、Java堆、Java虛擬機棧、本地方法棧、方法區
                   
           8、程序計數器(Program Counter Register)
                 一塊較小的內存空間,它的作用可以看作是當前線程所執行的字節碼的行號指示器
                 如果線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是Native方法,這個計數器值則為空。
                 此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域
 
二、Java虛擬機棧和本地方法棧
         1、Java虛擬機棧的概念和特征
               線程私有,后進先出棧,存儲棧幀,支撐Java方法的調用、 執行和退出
               可能出現StackOverflowError異常,如果棧被設計成可動態擴展,而在擴展的時候又申請不到足夠的內存,還可能出現OutOfMemoryError異常
         2、本地方法棧的概念和特征
                線程私有,后進先出棧,作用是支撐Native方法的調用、執行和退出
                可能出現StackOverflowError和OutOfMemoryError異常
                有一些虛擬機如HotSpot將Java虛擬機棧和本地方法棧合並實現
         3、棧幀的概念和特征
                Java虛擬機棧中存儲的內容,它被用於存儲數據和部分過程結果的數據結構,同時也被用來處理動態鏈接、方法返回值和異常分派
                一個完整的棧幀包含:局部變量表、操作數棧、動態連接信息、方法正常完成和異常完成信息
                局部變量表:由若干個Slot組成,長度由編譯期決定
                           單個Slot可以存儲一個類型為Boolean,byte,char,short,float,reference和returnAddress的數據,兩個Slot可以存儲一個類型為long或double的數據
                           局部變量表用於方法間參數傳遞,以及方法執行過程中存儲基礎數據類型的值和對象的引用
                操作數棧:由若干個Entry組成,長度由編譯期決定
 
三、Java堆
          1、Java堆的概念
                特征:全局共享,通常是Java虛擬機中最大的一塊內存區域,作用是作為java對象的主要存儲區域。JVMS明確要求該區域需要實現自動內存管理,即常說的GC,但並不限制采用哪種算法和技術去實現,可以在物理上不連續,可動態擴展,可能出現OutOfMemoryError
          2、棧與堆的討論
                 
四、方法區和運行時常量池
          1、方法區的概念
                 全局共享,作用是存儲Java類的結構信息,JVMS不要求該區域實現自動內存管理,但是商用虛擬機都能夠自動管理該區域的內存
          2、運行時常量池的概念
                  全局共享,是方法區的一部分,作用是存儲Java類文件常量池中的符號信息
          3、HotSpot方法區實現的變遷
                   在jdk1.2-jdk6,HotSpot使用永久代實現方法區
                   jdk7開始,HotSpot開始移除永久代的計划,符號表被移到Native Heap中,字符串常量和類的靜態引用被移到Java Heap中
                   jdk8開始,永久代已被元空間(Metaspace)所代替
 
五、直接內存
        並非JVMS定義的標准Java運行時內存區域
        隨JDK1.4中加入的NIO被引入,目的是避免在Java堆和Native堆中來回復制數據帶來的性能損耗
        全局共享,能被自動管理,但是在檢測手段上可能會有一些簡陋
        可能出現OutOfMemoryError異常
 
六、垃圾回收機制(GC Garbage Collection)
       1、什么是垃圾回收機制
            ① 顯示內存管理(C/C++):內存管理是程序開發者的職責
                  常見問題:
                   野指針:使用了一個指針,但是該指針指向的內存空間已經被free
                   內存泄露:內存空間已經申請,使用完畢后為主動釋放,會一直占用內存
            ② 自動內存管理(Java/C#/一些腳本語言):內存空間由垃圾回收期自動管理
                    優點:增加了程序的可靠性,減小了內存泄露和野指針的情況,提高了程序員的效率
                    缺點:程序員無法控制GC的時間
                          判斷哪些內存需要回收需要耗費系統開銷
                          邏輯上的內存泄露依然會存在
 
       2、GC的工作原理
             找出不再使用的對象,進行回收,所有不再使用的對象都是垃圾
       3、GC算法:
            Ⅰ.引用計數法:
               給堆中的每一個對象增加一個引用計數器,當每一次創建一個對象並賦值給一個變量時,引用計數器就加1;當對象不再使用時(出了作用域),引用計數器減1,當引用計數器為0,對象就滿足了垃圾回收的條件。
                特點:實現簡單
                缺點:循環引用的垃圾無法回收
            Ⅱ.根搜索算法(Root Tracing):
                在主流的商用程序處理語言中,都是使用根搜索算法來判斷隨想是否存活的。
                該算法的基本思路就是通過一系列的名為GC Root的對象作為起點,從這些節點開始向下搜索,搜索所走的路徑稱為引用鏈(Reference chain)。當一個對象到GC Root之間沒有任何引用鏈相連(用圖論的話來說就是GC Roots到這些對象不可達)時,證明該對象是不可用的,GC程序即可回收這些對象
                專業術語:
                 Shallow size:就是最像本身占用的內存大小,也就是對象頭加成員變量占用內存大小的總和
                 Retained size:是該對象自己的shallow size加上僅可以從該對象訪問(直接或間接訪問)的對象的shallow size之和。Retained size是該對象被GC之后所能回收的內存的總和
            Ⅲ.標記清除算法(Mark Sweep Algorithm):
               Dalvik使用標記清除算法實現垃圾回收
               1、mark:標記出被引用的對象
               2、sweep:清除哪些沒有任何引用的對象
               所有引用默認標記為0,每清除掉一個Root時,系統將從其他Roots能到達的引用都標記為1,垃圾回收將標記為0的對象回收掉,然后所有的標記置位0,重新開始新一輪垃圾回收
       4、GC觸發的時機
             申請Heap space失敗后會觸發GC,但此時已晚
             系統進入idle后一段時間會進行回收
             主動調用System.gc();進行回收






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM