- 相關(guān)推薦
如何識(shí)別Java中的內(nèi)存泄漏
Java開發(fā)人員都知道,Java利用垃圾回收機(jī)制來(lái)自動(dòng)保持應(yīng)用程序內(nèi)存的干凈和健康。然而可能有人不知道的是,即使使用了垃圾回收機(jī)制,Java中仍然可能存在內(nèi)存泄漏風(fēng)險(xiǎn)。如果你碰到下面的錯(cuò)誤代碼:
如果你確認(rèn)是內(nèi)存分配不足,那么可以通過(guò)以下代碼為應(yīng)用程序增加可用內(nèi)存:
不過(guò)對(duì)于內(nèi)存泄漏來(lái)說(shuō)這么做是治標(biāo)不治本,只能起到緩解作用。
內(nèi)存泄漏的識(shí)別
在將程序部署到生產(chǎn)環(huán)境之前檢查一下是否存在內(nèi)存泄漏的問(wèn)題是很有必要的。這里可以通過(guò)垃圾收集器的指標(biāo)來(lái)進(jìn)行初步的判斷。
如GC后內(nèi)存使用仍然持續(xù)上升,那么就可能有內(nèi)存泄漏的問(wèn)題,比如上面的這幅圖,代碼可以查看GitHub。不過(guò)在現(xiàn)實(shí)中內(nèi)存像圖上一樣線性增加的可能性是很小的,見圖Old Gen,而GC suspension times或者Eden Space和Survivor空間使用并不足以識(shí)別出內(nèi)存泄漏。
縮小問(wèn)題的范圍
要找出內(nèi)存泄漏的原因當(dāng)下已經(jīng)有許多工具可用,比如JVisualVM或者jStat。這些工具是JDK自帶的,所以大家隨時(shí)都能用。除了要識(shí)別一些常用的內(nèi)部Java類,一些用戶自定義累同樣需要識(shí)別。
性能優(yōu)化
在日常的開發(fā)過(guò)程中,只要GC沒(méi)有影響到性能,開發(fā)者就不會(huì)去關(guān)注內(nèi)存設(shè)置于配置。從而埋下了潛在的隱患:因?yàn)閮?nèi)存問(wèn)題并不只有溢出和泄露,GC時(shí)間過(guò)長(zhǎng)同樣會(huì)造成這個(gè)問(wèn)題。比如下圖中GC占用了16%的CPU。
Heap設(shè)置
Heap太小會(huì)導(dǎo)致頻繁的GC,從而情景不難想象:增加GC會(huì)消耗更多的CPU,同時(shí)在GC時(shí)JVM會(huì)被凍結(jié),最后導(dǎo)致一個(gè)很差的性能。總的來(lái)說(shuō),Heap太小的話,雖然GC時(shí)間變短,但是會(huì)變得更加頻繁。
Heap太大會(huì)導(dǎo)致GC時(shí)間邊長(zhǎng)。GC不會(huì)經(jīng)常發(fā)生,但是一旦被觸發(fā),那么VM會(huì)被凍結(jié)很久。
因此,如果這種情況下發(fā)生內(nèi)存泄露,在最終JVM因?yàn)閮?nèi)存溢出崩潰之前,GC會(huì)非常頻繁或者時(shí)間特別長(zhǎng)。
GC版本
從Java 6開始,GC就改變了很多。Java 7引入了G1GC作為CMS GC的替代選擇,而在Java 9中G1GC已成為默認(rèn)選擇。Java 8中移除了PermGen Space,之前存儲(chǔ)在PermGen Space中的數(shù)據(jù)則改為存儲(chǔ)在本地內(nèi)存或者棧中。
【如何識(shí)別Java中的內(nèi)存泄漏】相關(guān)文章:
如何解決java內(nèi)存泄漏07-26
如何解決java內(nèi)存泄漏的問(wèn)題08-13
Java內(nèi)存回收07-17
Java的內(nèi)存模型09-22
java程序運(yùn)行時(shí)內(nèi)存如何分配09-28
java內(nèi)存的詳細(xì)介紹06-04
JAVA中如何執(zhí)行DOS命令07-23