JVM学习初整理
JVM
內存結構(運行時數據區):堆(Heap),方法區(Method area),棧(本地方法棧(Native Method Stacks),虛擬機方法棧(Java ?Virtual Machine Stacks)),程序計數器(The pc Register)
堆:java虛擬機所管理的內存中最大的一塊;在虛擬機啟動時創建,被所有線程共享,java對象實例及數組都在堆上分配
方法區:Java虛擬機規范把方法區描述為堆的一個邏輯部分,別名Non-Heap,目的是與java堆區分開來,在java虛擬機啟動時創建,被所有線程共享;用于存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯后的代碼等數據;當方法區無法滿足內存要求時拋出OutOfMemoryError異常
虛擬機棧:是一個線程執行的區域,保存著一個線程中方法的調用狀態;
? ? ? ? ? ? ? 1:一個JAVA線程的運行狀態由一個虛擬機棧保存,所以虛擬機棧是線程私有的,隨著線程的創建而創建
? ? ? ? ? ? ? 2:每一個被線程執行的方法為該棧中的棧幀,即每個方法對應一個棧幀;調用一個方法就會向棧中壓入一個棧幀,一個方法調用完成,就會把該棧幀從棧中彈出(FILO先壓入的棧幀后彈出)
程序計數器:線程的執行權由CPU時間分片輪換調度,當一個線程執行過程中失去了執行權時由程序計數器記錄當前線程執行的位置,待線程再次獲得執行權時由程序計數器記錄的位置處開始執行
? ? ? ? ? ? ? ?1:如果線程正在執行的是JAVA方法,則計數器記錄的是正在執行的虛擬機字節碼指令的地址
? ? ? ? ? ? ? ?2:如果線程正在執行的是native方法,則這個計數器為空
本地方法棧:如果線程執行的是native方法,這些方法就會在本地方法棧中執行;如果在JAVA方法中調用native方法,則以動態鏈接的方式執行調用
內存結構(概念):老年代(old),新生代(Eden,survive0,survice1)
垃圾回收(GC):
? ? Eden:1:在JAVA對象的頭部(markWord)中會存儲當前的對象GC次數,當一個對象GC次數大于18時會將此對象從新生代轉移到老年代
? ? ? ? ? ? ? ? 2:當有較大的對象進入Eden區時,首先會將Eden存在的不連續空間的對象轉移到survive0區;當survive0區中的對象總內存超過survive0區的一半時,將survive0區中對象復制到survive1區中以便在survive0區中空出連續的完整空間
? ? ? ? ? ? ? ? 3:當占有超過Eden區內存一半的對象時,會直接存放到老年代
? 什么時候會進行垃圾回收:
? ? ? ? ? ? ? ? ?1:當Eden區或S區內存不夠用了
? ? ? ? ? ? ? ? ?2:老年代空間不夠用了
? ? ? ? ? ? ? ? ?3:方法區空間不夠用了
? ? ? ? ? ? ? ? 4:System.gc()
垃圾回收算法:標記-清除,標記復制
? ?可達性分析算法:通過GC Root對象(能作為GC Root:類加載器,Thread,虛擬機棧的本地變量表,static成員,常量引用,本地方法棧的變量等)開始向下尋找,看某個對象是否可達,不可達的對象標記回收
標記-清除(Mark ?Sweep)
? ? 標記:找出內存中需要回收的對象,并且把它們標記出來。此時堆中的所有對象都要被掃描一遍,才能確定需要被回收的對象,比較耗時。
? ? 清除: 清除掉被標記需要回收的對象,釋放出對應的內存空間。
? ? 缺點: ?標記清除之后會產生大量不連續的內存碎片,空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續內存而不得不提前觸發另一次垃圾收集動作。
標記-復制(Mark Copying)
? ? ? 將內存劃分為兩塊相等的區域,每次只使用其中一塊,當其中一塊使用完了,就將還存活的對象復制到另外一塊內存上,然后把已使用過的內存空間一次清除掉。
? ? ?缺點:空間利用率降低
標記-整理(Mark Compact)
? ? ?標記過程與“標記清除算法”一致,但后續步驟不是直接對可回收對象進行清理,而是讓存活對象都向一端移動,然后直接清理掉端邊界以外的內存。 相較于“標記復制算法”來說少了一個“保留區”。
?Young區:復制算法(對象在被分配之后,可能生命周期比較短,Young區復制率較高)
?Old區:標記清除或整理(Old區對象存活時間比較長,復制來復制去沒有必要,不如做個標記再整理)
?垃圾收集器分類:
? ? ? ? 串行收集器:Serial、Serial Old
? ? ? ? 只能有一個垃圾回收線程執行,用戶線程暫停;適用于內存比較小的嵌入式設備
? ? ? ? 并行收集器(吞吐量優先):Parallel Scanvenge、 Parallel Old
? ? ? ? ?多條垃圾回收線程并行工作,但此時用戶線程仍然處理等待狀態;適用于科學計算,后臺處理等交互場景
? ? ? ? 并發收集器(停頓時間優先):CMS、G!
? ? ? ? 用戶線程和垃圾收集線程同時執行(可能是交替執行),垃圾收集線程在執行的時候不會停頓用戶線程的運行;適用于相對時間有要求的場景,比如Web
內存泄漏與內存溢出的區別
內存泄漏是指不再使用的對象無法得到及時的回收,持續占用空間,從而造成內存空間的浪費。
內存泄漏很容易導致內存溢出,但內存溢出不一定是內存泄漏導致的
JVM查看參數
java -XX:+PrintFlagsFinal -version > flags.txt
常用命令:
jps:查看java進程
jinfo:實時查看和調整JVM配置參數
? ? ? ? ? 1:查看某個java進程某個屬性值: jinfo -flag name PID
? ? ? ? ? 2:修改某個屬性值:jinfo -flag [+ | -] PID? ? /? ? ?jinfo -flag <name>=<value> PID
? ? ? ? ? 3:查看曾經賦過值的一些參數? jinfo -flags PID
? jstat:查看虛擬機性能統計信息
? ? ? ? ? 1:jstat -class PID 1000 10? ?查看某個java進程的類裝載信息? 沒1000ms輸出一次共輸出10次
? ? ? ? ? 2:jstat -gc PID 1000 10 查看垃圾收集信息
jstack:查看線程堆棧信息? ? jstack PID? 檢測死鎖,? 或者使用jconsole工具也可檢測死鎖
jmap:生成堆轉儲快照
? ? ? ? ? ?1:jmap -heap PID 打印堆內存相關信息
? ? ? ? ? ?2:jmap -dump:format=b,file=heap.hprof PID? dump出堆內存相關信息
? ? ? ? ? ?3:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof? 內存溢出時自動dump堆內存相關信息
常用參數含義
總結
- 上一篇: 神策数据新 DEMO 上线,助力零售行业
- 下一篇: linux 网卡聚合mac,linux网