日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jvm性能调优 - 03垃圾回收机制

發(fā)布時間:2025/3/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jvm性能调优 - 03垃圾回收机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • Pre
  • 對象的分配與引用
  • 一個方法執(zhí)行完畢之后會怎么樣?
  • 不再需要的那些對象應(yīng)該怎么處理?--GC
  • 思考題


Pre

上一篇文章給大家分析了JVM中的幾塊內(nèi)存區(qū)域分別都是干什么的,今天的文章就給大家初步介紹一下垃圾回收的概念。

先來看一下昨天的一張圖,回顧一下JVM中幾塊內(nèi)存區(qū)域的作用。


大家腦子里一定要有一個會動的圖,你的代碼在運行的時候,起碼有一個main線程會去執(zhí)行所有的代碼,當(dāng)然也可能是你啟動的別的線程。

然后線程執(zhí)行時必須通過自己的程序計數(shù)器來記錄執(zhí)行到哪一個代碼指令了

另外線程在執(zhí)行方法時,為每個方法都得創(chuàng)建一個棧幀放入自己的Java虛擬機(jī)棧里去,里面有方法的局部變量。

最后就是代碼運行過程中創(chuàng)建的各種對象,都是放在Java堆內(nèi)存里的。

結(jié)合上面的大圖看一看,相信大家一定就明白是怎么回事了,大家對JVM的運行原理也應(yīng)該都有了一個初步的理解和把握。


對象的分配與引用

現(xiàn)在我們假設(shè)有下面一段代碼,大概意思你可以理解為通過“l(fā)oadReplicasFromDisk”方法的執(zhí)行,去磁盤上加載需要的副本數(shù)據(jù)

然后通過“ReplicaManager”對象實例完成了這個操作。

代碼如下所示:


結(jié)合我們之前理解過的JVM運行原理,一起通過動態(tài)的圖來拆解一下上述代碼的運行流程。

首先一個main線程肯定會來執(zhí)行main()方法里的代碼

main線程自己是有一個Java虛擬機(jī)棧的,他會把main()方法的棧幀壓入Java虛擬機(jī)棧,如下圖

接著main()方法里調(diào)用了loadReplicasFromDisk()方法

那么就會創(chuàng)建loadReplicasFromDisk()方法的棧幀,壓入main線程的Java虛擬機(jī)棧里去

這個過程如下圖:


此時發(fā)現(xiàn)在loadReplicasFromDisk()方法里,有一個“repliaManager”變量,那么就會在loadReplicasFromDisk()方法對應(yīng)的棧幀里,放入一個“repliaManager”變量。


接著發(fā)現(xiàn)在代碼里創(chuàng)建了一個“ReplicaManager”類的實例對象,此時就會在Java堆內(nèi)存中分配這個實例對象的內(nèi)存空間。

同時,讓loadReplicasFromDisk()方法的棧幀內(nèi)的“replicaManager”局部變量去指向那個Java堆內(nèi)存里的ReplicaManager實例對象,大家看下圖:


接下來,就會執(zhí)行通過“replicaManager”局部變量引用的“ReplicaManager”實例對象去執(zhí)行他的load()方法,去完成我們實現(xiàn)的業(yè)務(wù)邏輯。

好,到這里為止,其實都是上篇文章講解過的知識,我們就是重新串聯(lián)了一遍 ~


一個方法執(zhí)行完畢之后會怎么樣?

接著大家來回顧一下上面的代碼。

其實目前的圖我們已經(jīng)表述到了“replicaManager.load()”這行代碼這里

那么現(xiàn)在有個問題,如果這行代碼執(zhí)行結(jié)束了,此時會怎么樣? 一旦方法里的代碼執(zhí)行完畢,那么方法就執(zhí)行完畢了,也就是說loadReplicasFromDisk()方法就執(zhí)行完畢了。

一旦你的loadReplicasFromDisk()方法執(zhí)行完畢,此時就會把loadReplicasFromDisk()方法對應(yīng)的棧幀從main線程的Java虛擬機(jī)棧里出棧


此時一旦loadReplicasFromDisk()方法的棧幀出棧,那么大家會發(fā)現(xiàn)那個棧幀里的局部變量,“replicaManager”,也就沒有了。

也就是說,沒有任何一個變量指向Java堆內(nèi)存里的“ReplicaManager”實例對象了。

核心點來了,此時大家發(fā)現(xiàn)了,Java堆內(nèi)存里的那個“ReplicaManager”實例對象已經(jīng)沒有人引用他了

這個對象實際上已經(jīng)沒用了,該干的事兒都干完了,現(xiàn)在你還讓他留在內(nèi)存里干啥呢?

大家要知道,內(nèi)存資源是有限的。

一般來說,我們會在一臺機(jī)器上啟動一個Java系統(tǒng),機(jī)器的內(nèi)存資源是有限的,比如就4個G的內(nèi)存

然后我們啟動的Java系統(tǒng)本質(zhì)就是一個JVM進(jìn)程,他負(fù)責(zé)運行我們的系統(tǒng)的代碼 。

那么這個JVM進(jìn)程本身也是會占用機(jī)器上的部分內(nèi)存資源,比如占用2G的內(nèi)存資源。

那么我們在JVM的Java堆內(nèi)存中創(chuàng)建的對象,其實本質(zhì)也是會占用JVM的內(nèi)存資源的,比如“ReplicaManager”實例對象,會占用500字節(jié)的內(nèi)存。

所以大家看到這里,心中應(yīng)該無比明白的一個核心點:我們在Java堆內(nèi)存里創(chuàng)建的對象,都是占用內(nèi)存資源的,而且內(nèi)存資源有限。


不再需要的那些對象應(yīng)該怎么處理?–GC

繼續(xù)思考上面的圖,既然“ReplicaManager”對象實例是不需要使用的,已經(jīng)沒有任何方法的局部變量在引用這個實例對象了,而且他還空占著內(nèi)存資源,那么我們應(yīng)該怎么處理呢?

JVM的垃圾回收機(jī)制

JVM本身是有垃圾回收機(jī)制的,他是一個后臺自動運行的線程

你只要啟動一個JVM進(jìn)程,他就會自帶這么一個垃圾回收的后臺線程。

這個線程會在后臺不斷檢查JVM堆內(nèi)存中的各個實例對象

還是給大家畫一張圖,來看看這個過程:


如果某個實例對象沒有任何一個方法的局部變量指向他,也沒有任何一個類的靜態(tài)變量,包括常量等地方在指向他。

那么這個垃圾回收線程,就會把這個沒人指向的“ReplicaManager”實例對象給回收掉,從內(nèi)存里清除掉,讓他不再占用任何內(nèi)存資源。

這樣的話,這些不再被人指向的對象實例,即JVM中的“垃圾”,就會定期的被后臺垃圾回收線程清理掉,不斷釋放內(nèi)存資源


到此為止,相信大家跟上文章思路一路看下來,就很清晰明了。到底什么是JVM中的“垃圾”?什么又是JVM的“垃圾回收”!


思考題

既然今天提到了Java堆內(nèi)存里的對象會被回收掉,那么加載到方法區(qū)的類會被垃圾回收嗎?什么時候被回收?為什么呢?

  • 首先該類的所有實例對象都已經(jīng)從Java堆內(nèi)存里被回收

  • 其次加載這個類的ClassLoader已經(jīng)被回收

  • 最后,對該類的Class對象沒有任何引用

滿足上面三個條件就可以回收該類了

總結(jié)

以上是生活随笔為你收集整理的jvm性能调优 - 03垃圾回收机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。