GC(垃圾收集)烧栋,那收集回收的是什么呢?是內存拳球,所以在了解垃圾回收機制之前审姓,要對Java內存有一個了解。
一醇坝,Java內存
圖解:
私有內存區(qū)——伴隨線程的產生而產生邑跪,一旦線程終止,私有內存區(qū)也會自動消除
程序計數器:指示當前程序執(zhí)行到了哪一行呼猪,執(zhí)行Java方法時記錄正在執(zhí)行的虛擬機字節(jié)碼指令地址画畅;執(zhí)行本地方法時,計數器值為null
虛擬機棧:用于執(zhí)行Java方法宋距,棧針存儲布局邊聊表轴踱,操作數棧,動態(tài)鏈接谚赎,方法返回地址和一些額外的符加信息淫僻。程序執(zhí)行時入棧;執(zhí)行完成后棧針出棧壶唤。
GC主要就是在Java堆中進行的雳灵。
Java堆:Java虛擬機管理的內存中最大的一塊,所有線程共享闸盔,幾乎所有的對象實例和數組都在這類分配內存悯辙。
堆內存又分為:新生代和老年代,并且一般新時代的空間比老年代大。
了解了Java內存躲撰,接下來就來了解一下GC原理:
二.垃圾回收機制
一)GC的主要任務:
1.分配內存针贬;
2.確保被引用對象的內存不被錯誤的回收;
3.回收不再被引用的對象的內存空間
二)垃圾回收機制的主要解決問題
1.哪些內存需要回收拢蛋?
2.什么時候回收桦他?
3.如何回收?
針對問題一谆棱,垃圾收集器會對堆進行回收前快压,確定對象中哪些是“存活”,哪些是”死亡“(不可能再被任何途徑使用的對象)
判斷方法:
1.引用計數算法
每當一個地方引用它時础锐,計數器+1嗓节;引用失效時荧缘,計數器-1皆警;計數值=0——不可能再被引用。
//舉例:
? ? ? ? Test test1 = new Test();
? ? ? ? Test test2 = new Test();
? ? ? ? test1.obj = test2;
? ? ? ? test2.obj = test1;
? ? ? ? //test1 截粗,test12能否被回收信姓?
? ? ? ? System.gc();
1
2
3
4
5
6
7
查看運行結果,會發(fā)現并沒有因為兩個對象互相引用就沒有回收绸罗,因此引用計數算法很難解決對象之間相互矛盾循環(huán)引用的問題意推。
2.可達性分析算法:
向圖,樹圖珊蟀,把一系列“GC Roots”作為起始點菊值,從節(jié)點向下搜索,路徑稱為引用鏈育灸,當一個對象到GC Roots沒有任何引用鏈相連腻窒,即不可達時,則證明此對象時不可用的磅崭。
舉例:一顆樹有很多丫枝儿子,其中一個分支斷了,跟樹上沒有任何聯系砸喻,那就說明這個分支沒有用了柔逼,就可以當垃圾回收去燒了。
注:在Java中可作為GCRoots的對象:
1).虛擬機棧(棧幀中的本地變量表)中引用的對象割岛;
2).方法區(qū)中類靜態(tài)屬性引用的對象愉适;
3).方法區(qū)中常量引用的對象;
4).本地方法棧中JNI引用的對象
針對問題2——什么時候回收癣漆?
即使是被判斷不可達的對象维咸,也要再進行篩選,當對象沒有覆蓋finalize()方法,或者finalize方法已經被虛擬機調用過腰湾,則沒有必要執(zhí)行雷恃;
如果有必要執(zhí)行——放置在F-Queue的隊列中——Finalizer線程執(zhí)行。
注意:對象可以在被GC時可以自我拯救(this)费坊,機會只有一次倒槐,因為任何一個對象的finalize()方法都只會被系統(tǒng)自動調用一次。并不建議使用附井,應該避免讨越。使用try_finaly或者其他方式。
問題3——如何回收,這就牽扯到垃圾收集算法和垃圾收集器
垃圾收集算法:
1.標記—清除算法
兩個階段:標記永毅,清除把跨;
不足:效率問題;空間問題(會產生大量不連續(xù)的內存碎片)
2.復制算法
將可用內存按容量分為大小相等的兩塊沼死,每次都只使用其中一塊着逐;
不足:將內存縮小為了原來的一半
新生代
3.標記—整理算法
標記,清除(讓存活的對象都向一端移動)
老年代
垃圾收集器:
最后來講一下流程意蛀。
新建的對象再新生代中耸别,如果新生代內存不夠,就進行Minor GC釋放掉不活躍對象县钥;如果還是不夠秀姐,就把部分活躍對象復制到老年代中,如果還是不夠若贮,就進行MajorGC釋放老年代省有,如果還是不夠,JVM會拋出內存不足谴麦,發(fā)生oom蠢沿,內存泄漏。
額外參考資料:
https://blog.csdn.net/weixin_41835916/article/details/81530733
JVM性能調優(yōu)建議:
jvm調優(yōu)沒有一個固定模板配置說必須如何操作细移,它需要根據系統(tǒng)的情況不同對待搏予。
但是可以有如下建議:
1、初始化內存和最大內存盡量保持一致弧轧,避免內存不夠用繼續(xù)擴充內存雪侥。最大內存不要超過物理內存,例如內存8g精绎,你可以設置最大內存4g/6g但是不能超過8g否則加載類的時候沒有空間會報錯速缨。
2、gc/full gc頻率不要太高代乃、每次gc時間不要太長旬牲、根據系統(tǒng)應用來定仿粹。