JVM學習之內存模型

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq_34560242/article/details/81004768

一、JVM結構

這裏寫圖片描述

二、運行時數據區分爲以下幾塊空間:

  • 1、堆(Heap):保存所有引用類型的真實數據,此區爲共享區。
  • 2、虛擬機棧(VM Stack):虛擬機棧描述的是Java 方法執行的內存模型:每個方法被執行的時候都會同時創建一個棧幀(Stack Frame)用於存儲局部變量表、操作棧、動態鏈接、方法出口等信息。
    這裏寫圖片描述
    方法調用時棧幀的動作:
    這裏寫圖片描述
  • 3、方法區(Method Data Area):所有定義的方法的信息都保存在方法區之中,此區爲共享區。
  • 4、程序計數器:程序計數器是一塊較小的內存空間,可以看作是當前線程所執行的字節碼的行號指示器。分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。
  • 5、本地方法棧:本地方法棧(Native MethodStacks)與虛擬機棧所發揮的作用是非常相似的,其區別不過是虛擬機棧爲虛擬機執行Java 方法(也就是字節碼)服務,而本地方法棧則是爲虛擬機使用到的Native 方法服務。

三、JVM堆分爲三塊:

這裏寫圖片描述

這裏寫圖片描述

  • 年輕代:新對象和沒達到一定年齡的對象都在年輕代。

    • 1、伊甸園區:所有的新對象都在伊甸園區產生。
    • 2、存活區:存活區分爲兩塊相等大小的區域S0和S1。伊甸園區中經過多次Minor GC後還存活的活躍對象將會晉升到存活區。

      分爲兩塊相同大小區域的目的:一塊爲了晉升,一塊爲了對象回收。這兩塊內存空間一定有一塊是空的。

    • 3、伸縮區:用於調整年輕代內存大小的緩衝區。

      修改年輕代內存調整參數:
      這裏寫圖片描述
      例如:-Xmx16g -Xms16g -XX:SurvivorRatio=6 -XX:+PrintGCDetails
      設置Eden區和Survivor爲“6:1:1”

    年輕代GC(Minor GC)回收算法

    這裏寫圖片描述
    描述:將伊甸園區的存活對象複製到存活區兩塊區域中空的那塊,然後另外一塊區域中的活躍對象根據其存活時間判斷是保存到另塊空間還是保存到老年代。然後清除不活躍對象,騰出空間。
    在整個處理過程中,伊甸園區中保存的對象有可能大部分都臨時對象,那麼這樣就有可能頻繁的發生Minor GC,所以在HotSpot虛擬機中爲了加快此空間的內存分配,採用了兩種技術:
    1、Bump-The-Pointer
    這裏寫圖片描述
    缺點:多線程下有多個對象並行創建,就會影響性能。
    2、TLAB(Thread-Local-Allocation Buffers)
    這裏寫圖片描述

  • 老年代:被長時間使用的對象,老年代的內存空間比年輕代大。如果保存的對象超過了伊甸園區的內存大小,此對象將直接保存到老年代。
    這裏寫圖片描述
    例如:-Xmx16g -Xms16g -XX:PretenureSizeThreshold=512k -XX:+PrintGCDetails
    如果有超過512k的對象直接保存到老年代,這個對象不會再觸發Minor GC。

    老年代GC(Major GC/Full GC)回收算法

    • 1、標記-清除
      這裏寫圖片描述
      先對老年代中不活躍對象進行標記,標記完成之後進行清除,不會對清除後的空間進行整理,會導致內存碎片化問題。
    • 2、標記-壓縮
      這裏寫圖片描述
      先對老年代中不活躍對象進行標記,標記完成之後進行清除,清除之後再對空間碎片進行整理壓縮。
  • 永久代和元空間:永久代在JDK1.8之後被元空間替代。目的是將HotSpot與JRockit兩個虛擬機標準統一。

    • 永久代(JDK1.8以前):永久代是在堆內存中保存的,但是永久代不會被回收,例如:intern()產生的對象就不會被回收。如果操作不當,導致永久代內存溢出,也會拋出“OutOfMemoryError”異常。

      永久代參數調整:
      這裏寫圖片描述
      例如:-XX:MaxPermSize=10m 結果:
      Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10m; support was removed in 8.0
      在JDK1.8之後就不存在永久代的設置了。

    • 元空間(JDK1.8以後):功能和永久代沒太大區別。唯一的區別是永久代使用的堆內存而元空間是使用的物理內存。

      元空間內存參數調整:
      這裏寫圖片描述
      例如:-XX:MetaspaceSize=1m -XX:MaxMetaspaceSize=1m
      Error occurred during initialization of VM
      OutOfMemoryError: Metaspace
      如果元空間內存太小也會“OOM”

四、堆內存參數調整(測試機器內存24G)

這裏寫圖片描述

這裏寫圖片描述

  • 1、初始化內存和最大內存

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long totalMemory = runtime.totalMemory();
        System.out.println("maxMemory:" + maxMemory / 1024 / 1024 + "M");
        System.out.println("totalMemory:" + totalMemory / 1024 / 1024 + "M");
    }
    
    maxMemory:5452M
    totalMemory:368M

    可以發現:默認情況下分配的內存是總內存的“1/4”,初始化內存大小是物理內存的“1/64”,也就是說可變內存是物理內存的“1/64 ~ 1/4”。

    手動指定最大內存和初始化內存 -Xmx8G -Xms8G 再次輸入結果爲:

    maxMemory:7851M
    totalMemory:7851M

    這個時候就避免了伸縮區的可調策略,從而提高了程序的性能

  • 2、觀察GC的詳細日誌:-XX:+PrintGCDetails

    控制檯輸出:

    maxMemory:7851M
    totalMemory:7851M
    Heap
    PSYoungGen      total 2446848K, used 167813K [0x0000000715580000, 0x00000007c0000000, 0x00000007c0000000)
    eden space 2097664K, 8% used [0x0000000715580000,0x000000071f961618,0x0000000795600000)
    from space 349184K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007c0000000)
    to   space 349184K, 0% used [0x0000000795600000,0x0000000795600000,0x00000007aab00000)
    ParOldGen       total 5592576K, used 0K [0x00000005c0000000, 0x0000000715580000, 0x0000000715580000)
    object space 5592576K, 0% used [0x00000005c0000000,0x00000005c0000000,0x0000000715580000)
    Metaspace       used 3532K, capacity 4498K, committed 4864K, reserved 1056768K
    class space    used 387K, capacity 390K, committed 512K, reserved 1048576K

    PSYoungGen:新生代 3/8
    ParOldGen:老年代 5/8
    默認情況下新生代和老年代內存大小比例爲:3:5

  • 3、內存可視化工具:

    • 1、可視化工具:\jdk1.8.0_131\bin\jvisualvm.exe

      • 1)、繼續執行上步代碼,將內存調整爲最大內存調整爲16G,方便查看過程。

        -Xmx16g -Xms16g -XX:+PrintGCDetails
      • 2)、運行程序,打開jvisualvm.exe找到當前執行的進程,打開監視,可以觀察到CPU、堆等使用情況。
        這裏寫圖片描述
        這裏寫圖片描述
    • 2、命令查看:jmap(jmap -heap PID)

      • 1)、運行程序,Windows下打開cmd,輸入taskList 找到 java.exe 觀察其PID

        C:\Users\Administrator>tasklist
        
        映像名稱                       PID 會話名              會話#       內存使用
        ========================= ======== ================ =========== ============
        java.exe                      10280 Console                    1  5,241,504 K
      • 2)、再輸入 jmap -heap 10280 即可觀察到內存使用情況

        C:\Users\Administrator>jmap -heap 10280
        Attaching to process ID 10280, please wait...
        Debugger attached successfully.
        Server compiler detected.
        JVM version is 25.131-b11
        
        using thread-local object allocation.
        Parallel GC with 8 thread(s)
        
        Heap Configuration:
        MinHeapFreeRatio         = 0
        MaxHeapFreeRatio         = 100
        MaxHeapSize              = 734003200 (700.0MB)
        NewSize                  = 134217728 (128.0MB)
        MaxNewSize               = 244318208 (233.0MB)
        OldSize                  = 268435456 (256.0MB)
        NewRatio                 = 2
        SurvivorRatio            = 8
        MetaspaceSize            = 21807104 (20.796875MB)
        CompressedClassSpaceSize = 1073741824 (1024.0MB)
        MaxMetaspaceSize         = 17592186044415 MB
        G1HeapRegionSize         = 0 (0.0MB)
        
        Heap Usage:
        PS Young Generation
        Eden Space:
        capacity = 100663296 (96.0MB)
        used     = 18841312 (17.968475341796875MB)
        free     = 81821984 (78.03152465820312MB)
        18.717161814371746% used
        From Space:
        capacity = 16777216 (16.0MB)
        used     = 6625856 (6.31890869140625MB)
        free     = 10151360 (9.68109130859375MB)
        39.49317932128906% used
        To Space:
        capacity = 16777216 (16.0MB)
        used     = 0 (0.0MB)
        free     = 16777216 (16.0MB)
        0.0% used
        PS Old Generation
        capacity = 268435456 (256.0MB)
        used     = 81936 (0.0781402587890625MB)
        free     = 268353520 (255.92185974121094MB)
        0.03052353858947754% used
        
        5342 interned Strings occupying 461016 bytes.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章