自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

又抓了一個導(dǎo)致頻繁GC的鬼--數(shù)組動態(tài)擴容

開發(fā) 開發(fā)工具
只要保證在cms gc回收old之前做一次ygc就能保證新生代里的那個新數(shù)組被回收而沒有指向老生代那些byte數(shù)組,那么這些數(shù)組就能正常被cms gc回收了,所以加上-XX:+CMSScavengeBeforeRemark即可解此問題。

[[188700]]

概述

本周有個同事過來咨詢一個比較詭異的gc問題,大概現(xiàn)象是,系統(tǒng)一直在做cms gc,但是老生代一直不降下去,但是執(zhí)行一次jmap -histo:live之后,也就是主動觸發(fā)一次full gc之后,通過jstat -gcutil來看老生代一下就降下去了,初看下理論上不太可能,因為full gc也會對old做回收,于是我要同事針對他們的場景寫了一個簡單的demo出來,然后果然還真能重現(xiàn),不過他的demo設(shè)置的Heap有32G,于是我通過慢慢調(diào)整,最終在很小的內(nèi)存下也能重現(xiàn)出來。

Demo

測試代碼如下:

正如我上面注釋里寫的JVM參數(shù),控制新生代200M,老生代300M,老生代使用率達到90%的時候觸發(fā)CMS GC,大家可以跑跑看,這種情況下會發(fā)現(xiàn)不斷做CMS GC,但是老生代就是不降下去,但是只要你主動觸發(fā)一次Full GC,老生代立馬就會回收。

當(dāng)allocateMemory方法執(zhí)行完之后,期待的結(jié)果是gc之后List及里面的byte數(shù)組都應(yīng)該被回收掉,可是事實并不是這樣的。

初步定位

這段代碼非常簡單,我翻來覆去地看著這段代碼,視圖想改變點什么,能讓問題出現(xiàn)峰回路轉(zhuǎn),我不斷地控制for循環(huán)的次數(shù)和每次分配的內(nèi)存大小,最終我將目標轉(zhuǎn)移到那個ArrayList上,List里有個數(shù)組,在add過程中如果發(fā)現(xiàn)數(shù)組不夠了,于是會進行擴容,那擴容就是創(chuàng)建新的數(shù)組,將老的對象放到新數(shù)組里,那我試想要是不做擴容會不會有問題?于是我開始調(diào)整ArrayList的初始化大小,當(dāng)我調(diào)到一定大小,保證在add過程中不會做擴容,問題真出現(xiàn)了反轉(zhuǎn),居然能正?;厥樟?,比如上面的demo,將數(shù)組長度設(shè)置為len,那結(jié)果就完全不一樣了,老生代很快就被回收了。

那目標能鎖定到數(shù)組擴容了

數(shù)組擴容

ArrayList里的數(shù)組擴容,使用的是System.arrayCopy調(diào)用,這是一個native方法,在java層面創(chuàng)建一個新的長度的數(shù)組,然后將老數(shù)組和新數(shù)組都傳進去,在native里將老數(shù)組里的元素指針拷貝到新數(shù)組里,其實做的是淺拷貝,反復(fù)看native這塊實現(xiàn),也基本解釋不通那個現(xiàn)象,一度懷疑我對GC的理解了,是不是有哪些細節(jié)沒有注意到。

經(jīng)過我內(nèi)存dump分析,發(fā)現(xiàn)上面Demo里的List對象確實被回收了,但是List里的數(shù)組沒有被回收,這個數(shù)組里的byte數(shù)組都沒有被回收。

原來是這個鬼

帶著百思不得其解的疑惑和我們組同事討論,看看還有沒有其他可能的沒考慮到疑惑點,開始也都覺得疑惑,后來傳勝突然想到會不會是存在跨代引用的問題,于是回過來仔細再想想每個步驟,好像還真有可能,因為傳給System.arrayCopy的新數(shù)組是在java層面構(gòu)建傳進來的,在新生代分配的可能性***,這樣再加上拷貝僅僅是淺拷貝,那么老生代里的byte數(shù)組因為存在新生代里新書組的引用,那僅僅做CMS GC就不可能回收這些老生代的對象了,因為CMS GC的一個gc root就是新生代里的對象。

那何解

至此終于抓出了那個鬼,于是想應(yīng)對策略,既然這樣,只要保證在cms gc回收old之前做一次ygc就能保證新生代里的那個新數(shù)組被回收而沒有指向老生代那些byte數(shù)組,那么這些數(shù)組就能正常被cms gc回收了,所以加上-XX:+CMSScavengeBeforeRemark即可解此問題。

【本文是51CTO專欄作者李嘉鵬的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(你假笨,id:lovestblog)聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2017-04-19 12:09:56

數(shù)組動態(tài)擴容GC

2021-11-12 08:07:31

SQL緩存RabbitMQ

2017-06-27 08:41:04

JVM設(shè)計缺陷GC

2024-03-15 08:18:25

volatileAtomic關(guān)鍵字

2012-08-16 10:43:10

GC

2013-05-02 10:40:24

xcode

2014-05-23 10:37:37

聊天程序PHP聊天程序

2015-04-27 10:39:26

程序員

2015-12-09 14:53:58

開源手機系統(tǒng)

2015-05-11 09:26:15

Android M谷歌

2021-09-11 19:00:54

Intro元素MemoryCache

2013-06-03 15:38:16

iOS開發(fā)iOS SDK動態(tài)Action Sh

2023-04-30 12:44:28

GC應(yīng)用性能

2014-02-26 11:18:02

Android開發(fā)偷懶高效

2015-05-21 15:45:13

2025-03-31 04:25:00

2023-02-26 01:02:22

2020-10-23 06:56:00

C語言動態(tài)字符串

2022-08-29 08:28:58

JS對象數(shù)組

2021-11-19 11:36:42

語言string字符串
點贊
收藏

51CTO技術(shù)棧公眾號