當前位置:網站首頁>JVM腦圖

JVM腦圖

2022-01-28 10:28:06 WuSong1999

JVM
類裝載器
根加載器,像 Object 這些類,在一啟動的時候,就通過 Bootstrap 啟動類加載器加入
到了 jvm ,所以可以直接使用
擴展類加載器,在 jdk 不停的更新途中,加入了很多新的 jar 包,這些 jar 包就使用擴
展類加載器 Extension 加入到了 jvm
系統類加載器,自己在 java 項目中創建的 class 類,都會通過 AppClassLoader 系統類
加載器,加載當前應用的 classpath 的所有類進入到 jvm
雙親委派
一個類的加載先從根加載器找,根加載器找不到就去擴展類加載器找,擴展類找
不到就去系統類加載器中找。
沙箱安全機制
雙親委派機制就是為了保證沙箱安全機制,就不讓人幹壞事,不能替換掉 java
身自帶的一些類
線程私有: native 本地方法
native 是一個關鍵字
有聲明, java 無實現,是使用的 C 語言實現的第三方函數庫,
線程私有: PC 寄存器:程序計數器
行號計數器,用來存儲執行到了第幾行,多線程環境下會出現時間爭搶,如果當前
線程時間片用完,那麼就需要等待獲取到新的時間片來進行執行,那麼從等待重新
開始執行的時候,從哪一行開始執行就是用程序計數器來决定的
記錄了方法之間的調用和執行情况,類似排版值日錶,用來存儲指向下一條指令的
地址,也就是將要執行的指令代碼,它是當前線程所執行的字節碼的行號指示器
線程私有: stack :棧
棧管運行,堆管存儲
棧主管 java 程序的運行,在創建線程時創建,在線程結束時棧也釋放,棧不存在垃
圾回收問題,只要線程一結束該棧就 Over ,聲明周期和線程一致,是線程私有的
8 種基本類型的變量 + 對象的引用變量 + 實例方法都是在函數的棧內存中分配
棧幀鐘主要存儲三類數據
1 :本地變量,輸入參數和輸出參數以及方法內的變量
2 :棧操作,記錄出棧,入棧的操作
3 :棧幀數據,包括類文件,方法等等 java 方法 = 棧幀
每個方法執行的同時都會創建一個棧幀,用於存儲局部變量錶、操作數棧、動態鏈
接、方法出口等信息,每一個方法從調用直至執行完畢的過程,就對應著一個棧幀
在虛擬機鐘入棧到出棧的過程,棧幀的大小和具體 jvm 的實現有關,通常在
256K~756K 之間,約等於 1Mb 左右
java.lang.StackOverFlowError SOF :把棧撐爆了,是一個 Error 錯誤
線程共享:方法區
存在垃圾回收
方法區不是專門放方法的地方
供各線程共享的運行時內存區域,它存儲了每一個類的結構信息,運行時常量池、
字段和方法數據、構造函數和普通方法的字節碼內容
方法區是規範,在不同虛擬機裏面實現是不一樣的,最典型的就是永久代和元空間
空調 k1 = new 格力()
list list = new Arraylist ()
java 7 以前是:方法區 f = new 永久代
java 8 以後是:方法區 f = new 元空間
所以方法區是一個規範, new 的後面是具體的實現
線程共享: heap :堆
新生代
伊甸區: Eden 元區
new 出來的第一次都存放在這個區域
Eden 區滿了會開啟 ygc GC ,執行 ygc 後,大部門對象都會被 kill 掉,沒有被
kill 掉的幸存者就會轉移到幸存者 0
幸存者 0 區: Survivor 0
接收沒有被 ygc kill 掉的對象,幸存者 0 區和 1 區會進行交換,保證 0 1 兩個區
域一個存放活著的對象,一個啥都不存
幸存者 1 區: Survivor 1
GC 15 次(默認值 15 )沒被 kill 掉的會轉移到老年代
交換
from 區和 to 區,他們的比特置和名分,不是固定的,每次 GC 後會交換,誰空誰
to
老年代
如果老年代區域也滿了,就會開啟 full gc = FGC GC ,如果 full gc 多次,發現
空間沒辦法騰出來,那麼 jvm 就報 OOM 堆內存溢出异常 理論
新生區是類的誕生、成長、消亡的區域,一個類在這裏產生,應用,最後被垃圾
回收器收集,結束生命。新生區又分為兩部分:伊甸區和幸存者區,所有的類都
是在伊甸區被 new 出來的。幸存區有兩個: 0 區和 1 區。當伊甸園的空間用完時,
程序又需要創建對象, JVM 的垃圾回收器將對伊甸園區進行垃圾回收 Minor GC
GC ,將伊甸園區中的不再被其它對象所引用的對象進行銷毀。然後伊甸園中
的剩餘對象移動到幸存者 0 區,如果幸存者 0 區也滿了,再對該區進行垃圾回
收,然後移動到 1 區,那如果 1 區也滿了呢?再移動到養老區,若養老區也滿
了,那麼這個時候將產生 MajorGC FULLGC ,進行養老區的內存清理,若養老區
執行了 Full gc 之後依然無法進行對象的保存,就會產生 OOM
"OutOfMemoryError"
jdk8 以後元空間 /jdk7 之前永久代
堆內存調優
-Xms :設置初始分配大小,默認為物理內存的 1 / 64
-Xmx :最大分配內存,默認為物理內存的 1 / 4
-XX:+PrintGCDetails :輸出詳情的 GC 處理日志
實踐經驗
生產環境上的 java 應用, JVM -Xmx -Xms 兩個參數的值必須一致,防止內
存忽高忽低產生停頓
java.lang.OutofMemoryError java heap space :堆內存溢出
GC (分代收集算法)
次數上頻繁收集 Young
次數上較少收集 Old
基本不動元空間
GC 4 大算法
引用計數法
jvm 實現不采用這種方式
有一個計數器去記錄每個對象被引用的次數
缺點:較難處理循環引用,有個計數器消耗性能
複制算法
年輕代使用的垃圾回收算法就是複制算法
複制算法的基本思想就是將內存分為兩快( Eden 區和 from 區是一快 to 也是
一快),每次只用其中一快,當這一快內存用完,就將還活著的對象複制到
另外一快上面,複制算法不會產生內存碎片 因為 Eden 區對象一般存活率較低,一般的,使用兩塊 10% 的內存作為空閑和
活動區間,而另外 80% 的內存,則是用來給新建對象分配內存的,一旦發生
GC ,將 10% from 活動區間與另外 80% 中存貨的 Eden 對象轉移到 10% to
閑空間,接下來,將之前 90% 的內存全部釋放,以此類推
優點:速度快
缺點:浪費空間 浪費了一半內存,這太要命了
標記清除
老年代使用的就是標記清除與標記整理的混合實現
算法分成標記和清除兩個階段
先標記出要回收的對象
然後統一回收這些對象
缺點:
內存碎片過多
速度沒複制算法快,有標記和清除兩個操作
優點:
不需要額外的空間
標記壓縮
老年代使用的就是標記清除與標記整理的混合實現
也叫標記清除 + 標記整理算法,比標記清除多了一步整理的步驟
缺點:
速度慢
優點:
不會浪費空間和產生內存碎片
JDK9 之後
JAVA 9 的默認垃圾回收器
G1 垃圾回收器
G1 將新生代,老年代的物理空間劃分取消了,這樣我們再也不用單獨的空
間對每個代進行設置了,不用擔心每個代內存是否足够。
G1 算法將堆劃分為若幹個區域(
Region ),它仍然屬於分代收集器
https://www.kancloud.cn/luoyoub/jvm-note/2255980

版權聲明
本文為[WuSong1999]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/01/202201281028059210.html