JVM調優--GC基礎


該視頻是即將要參加的公開課視頻的前置內容

主要內容:Garbage Collector 和GC tuning

主講人是: 馬士兵

目標: 在正式上課之前的基礎課程. 


 整體上來講, 看了馬士兵的預習視頻以后, 感覺對GC又復習了一遍. 此次預習, 主要目的是7號晚上會有一個JVM調優的課程, 全稱也有幾點感悟

1. 理論偏多, 也就是更多的是概念性的問題.

2. 記得兩年前擼過一遍jvm內存模型, jvm GC, 當時學得很認真, 所以, 這次聽老師在講GC, 在理解上更近了一步. 可喜的是,當時的筆記記在哪里了?已經找不到了, 那是系統的學習,講解的更詳細.

3. 也是我思考的問題. 學習了這些東西, 要如何能夠應用在實際工作中. 學是第一步, 更重要的是用.

4. 期待今晚上的課程, 據說很有用

 

回到正題, 整理今天的筆記

以下是課程開始前, 馬老師給出的一個jvm的架構圖, 讓我垂涎欲滴的. 要是能夠全部掌握, 應該在代碼上會大進一步.


本節講解的主要內容如下:

GC的基礎知識

1. 什么是垃圾

  a. 在c c++ java中是如何申請內存, 又是如何回收的呢?

    c語言申請內存: malloc  / free

    c++ : new / delete

    java : new / 無

    java采用的是自動回收機制

  b. 手動回收和自動回收

    自動回收: 編程簡單, 系統部容易出錯, 但相對效率較低

    手動回收: 變成復雜, 容易出現以下兩類問題, 但效率高

    - 忘記回收

    - 多次回收

  c. 那么什么是GC呢? 沒有任何引用指向的一個對象或者一堆對象. 解釋一下

       

 

   棧空間里有一個對象, 這個對象new出來了一個成員變量, 這個變量指向了另外一個對象. 當我們把這個成員變量設置為null, 關系變為如下:

 

   這時, 這個對象就變成垃圾. 這是單個對象變為垃圾的情況. 

  還有一種. 如下:

 

   這種是,好多個對象互相之間有引用, 但是,沒有任何引用指向它, 那么, 他也是垃圾. 是一堆垃圾.

 

2. 如何定位垃圾

  兩種方法:

  1. Reference Count: 引用計數

 

   在一個對象上標記數字, 有幾個對象引用他了. 比如現在有3個, 這標記為3. 知道對象標記為0, 則認為他是一個垃圾

   引用計數存在的問題: 當一堆對象, 彼此相互引用, 他們的計數始終都不為0, 但是他們沒有被其他對象引用, 是一對垃圾, 通過引用計數沒法判斷, 所以, 又有下面這種計數方式--根可達算法

 

  2. Root Searching根可達算法: 

  

   通過程序找到根對象, 通過跟對象找到關聯的對象, 這些都不是垃圾, 其他的都是垃圾. 

  根對象指的是什么呢?

  程序運行, 會有一個main方法, 這個肯定不是垃圾. 

  線程棧里的局部變量, 靜態變量, 常量池, JNI指針引用到的變量.

  jvm 文檔給出的那些對象是根對象呢? JVM stack(棧對象), native method(本地方法棧), run-time constant(常量池), static references in method area(靜態方法區), Clazz(內存中的class)

3. 常見的垃圾回收算法

  a. Mark Sweep標記清除:

  

 

 

  標記黑色可回收的對象然后清楚. 優點是速度快, 缺點, 從清除后的圖像可以看出, 內存被分成了一小塊一小塊, 有碎片

  b. copy拷貝:

  

 

 

  將內存一分為二: 然后將第一部分的存活對象全部拷貝到第二部分. 在對第一部分整體清除.

  拷貝的速度是很快的, 缺點是耗費內存. 本來5G空間就足夠了, 但是用標記清楚, 就要配備10G的內存. 

  c. Mark Compact標記壓縮:

  

 

 

   將可回收對象標記出來,然后把后面的存活對象拷貝到可回收的位置, 在做標記和清除的過程中, 做了壓縮和整理.

  好處是有用的對象放一塊, 可以有整塊的空間, 資源也得到了充分的利用. 缺點是:效率偏低.

4. JVM分代內存模型

  a. 部分垃圾回收期使用的模型:

  b. 新生代New + 老年代Old + 永久代(1.7) / 元數據區(1.8) Metaspace

    1) 永久代和元數據都是裝class

    2)永久代必須指定大小限制, 元數據可以限制, 也可以不限制,無上限(受限於物理內存)

    3) 字符串常量 1.7-永久代, 1.8-元數據

  c. 新生代 = Eden + 2個survivor . 對新生代對象的回收叫YGC.

    1) YGC回收后,大多數會被回收. 活着的對象進入s1

    2) 再次YGC, 將Eden+s1對象copy到s2, 然后清空.

    3) 再次YGC, Eden + s2 對象 copy到s1, 以此循環

    4) 年齡達到一定階段, 直接放入老年代.

    5) 如果大對象s2放不下,直接進入老年代.

  d. 老年代: 

    1) 裝的頑固分子

    2) 垃圾回收叫FGC

 

  e. GC tuning(Generation) GC調優, 調什么呢?

    1) 盡量減少FGC

    概念: MinorGC 就是 YGC

        MajorGC 就是 FGC

 

      STW

  堆內存邏輯分析:

  

 

 

 

5. 垃圾回收器

  垃圾回收算法有哪些?

  

 

 

   紅線圈出的是分代模型, 上面是新生代使用的模型, 下面是老年代使用的模型, 右側跨在中間的不在區分新生代和老年代.

  線上運行的系統, 多數是紅線圈出的部分. 所以我們調優也是針對這部分. 仔細看, 新生代和老年代中間有虛線, 虛線代表組合.

  a. Serial : 串行回收

  

 

 

   hotspot是這么定義的: 停止整個世界, 進行單線程GC處理

  意思是: 藍線代表有多個線程正在執行, 然后, 要進行gc回收. 所有線程都要停止, gc回收線程是單線程. gc回收完, 繼續執行主任務, 依次循環.

  Serial 使用在新生代

  Serial Old 使用在老年代

  b. Parallel Scavenge: 並行回收

  Parallel Scavenge: 用在新生代

  Parallel Old: 用在老年代

  

 

 

  和Serial並行回收對比, 垃圾回收采用的是多線程並行回收. 效率比單線程高

  3. ParNew:配合CMS的並行回收, 應用在年輕代

  

 

 

   他也是並行回收, 那么他和Parallel Scavenge的區別是什么呢? 看hotspot給出的, 重點在於ParNew可以和CMS配合使用.

   d. ConcurrentMarkSweep: 簡稱CMS. 

    1) 應用在老年代

    2) 在垃圾回收的過程中, 應用程序也能運行. 所以叫做並行

    3)這個回收機制也存在各種問題, 達存在的意義是一個承上啟下的過度, 由此產生了下面幾種回收機制.

  

 

 

     詳細在下節課解釋

     5. G1:(10ms)

     6. ZGC: (1ms): 可以pkc++

     7. Shenandoah:

    8. Eplison

  目前,我們調優主要調的是哪一塊呢? Serial和Serial Old, Parallel Scavenge和Parallel Old.

  原因是: 1.8默認的垃圾回收器是PS + Parallel Old. 我們使用的時候很少去手動設置

6. jvm調優第一步, 了解生產環境下的垃圾回收組合

  a. JVM命令行參數的參考

  b. JVM命令參數分類

    1) 標准參數: -開頭, 所有的HotSpot都支持

      例如: java -version

    2)非標准參數: -X開頭, 特定版本的HotSpot支持

      在命令行輸出 java -X 可以查看到非標參數

    3)不穩定參數: -XX開頭, 下個版本可能取消

      在命令行輸出 java -XX:+PrintFlagsFinal

      java -XX:+PrintCommandLineFlags, 這個命令用來查看, 再生產環境中jvm使用了哪些參數. 不會影響線上程序的運行.

      

 

       這是我的java程序啟動的時候的參數

      1. InitialHeapSize :初始堆大小

      2. -XX: MaxHeapSize : 對最大大小

      3. -XX:+PrintCommandLIneFlags : 我當前執行的命令

      4. -XX:+UseCompressedClassPointers : 壓縮指針

      5. -XX:UseCompressedOops : 壓縮對象

      6. -XX: +UseParallelGC : 使用的GC是ParallelGC. 使用的就是(Parallel Scavenge + Parallel Old) .

    通過這個命令, 我們就知道我們使用的是什么樣的GC類型了. 我的java 是1.8

 


本次預習就結束了, 看了一遍, 有整理了一遍筆記, 期待晚上的分享. 

 


免責聲明!

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



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