您好,登錄后才能下訂單哦!
如何理解JVM的GC overhead limit exceeded錯(cuò)誤,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
java 中有幾個(gè)難兄難弟,比如我昨天寫的 java.lang.OutOfMemoryError: Java heap space 和今天要寫的 java.lang.OutOfMemoryError: GC overhead limit exceeded 等。要搞清這些知識(shí),就需要深入的理解 JVM 底層原理和實(shí)現(xiàn)機(jī)制。
那么我們今天就具體來說說 java.lang.OutOfMemoryError: GC overhead limit exceeded 吧!
我們都知道,Java 語言的一大優(yōu)勢就是內(nèi)存管理,也就是垃圾回收機(jī)制。相比其他語言,如:C++等,它們這些語言中并沒有自動(dòng)內(nèi)存回收機(jī)制, 需要程序員手工編寫代碼來進(jìn)行內(nèi)存分配和釋放, 以重復(fù)利用堆內(nèi)存。
也正是因?yàn)?Java 語言有自動(dòng)垃圾回收機(jī)制,所以一些程序員在使用不當(dāng)?shù)那闆r下,會(huì)發(fā)生一系列你意想不到的 OutOfMemoryError。關(guān)于 OutOfMemoryError 錯(cuò)誤,目前一共有 8 種,我們一一的來搞定它們!
java.lang.OutOfMemoryError: GC overhead limit exceeded 這種情況發(fā)生的原因是程序基本上耗盡了所有的可用內(nèi)存, GC 也清理不了。
更準(zhǔn)確的說法應(yīng)該是:執(zhí)行垃圾收集的時(shí)間比例太大,有效的運(yùn)算量太小。默認(rèn)情況下,如果GC花費(fèi)的時(shí)間超過 98%,并且GC 回收的內(nèi)存少于 2%,JVM 就會(huì)拋出這個(gè)錯(cuò)誤。
java.lang.OutOfMemoryError: GC overhead limit exceeded 錯(cuò)誤只在連續(xù)多次 GC 都只回收了不到2%的極端情況下才會(huì)拋出。假如不拋出 GC overhead limit 錯(cuò)誤會(huì)發(fā)生什么情況呢? 那就是 GC 清理的這么點(diǎn)內(nèi)存很快會(huì)再次填滿,迫使 GC 再次執(zhí)行。這樣就形成惡性循環(huán),CPU 使用率一直是 100%,而 GC 卻沒有任何成果。系統(tǒng)用戶就會(huì)看到系統(tǒng)卡死。以前只需要幾毫秒的操作,現(xiàn)在需要好幾分鐘才能完成。
下面我們來看一個(gè)產(chǎn)生“GC overhead limit exceeded” 錯(cuò)誤的例子:
為了能夠更快的看到效果,我們可以設(shè)置一下 JVM 的參數(shù):
需要注意的是,不同的 GC 算法。產(chǎn)生的錯(cuò)誤信息也不相同,有的可能會(huì)產(chǎn)生 java.lang.OutOfMemoryError: Java heap space 錯(cuò)誤。
關(guān)于具體的 GC 算法,我給大家一張關(guān)于 Java8 GC 算法的列表,我后面再具體的寫文章來講。
我們在說說上面產(chǎn)生 OutOfMemoryError 錯(cuò)誤的代碼吧。Map 在進(jìn)行 rehash 時(shí)拋出了 java.lang.OutOfMemoryError 錯(cuò)誤消息。如果使用其他垃圾收集算法,比如 -XX:+UseConcMarkSweepGC,或者 -XX:+UseG1GC,錯(cuò)誤將被默認(rèn)的 exception handler 所捕獲,但是沒有 stacktrace 信息,因?yàn)樵趧?chuàng)建 Exception 時(shí)沒辦法填充 stacktrace 信息。
再比如,有些廠商的 JVM 在 Win7x64,Java8 環(huán)境配置如下 UseG1GC:
結(jié)果產(chǎn)生的錯(cuò)誤信息卻是:
上面這些真實(shí)的案例表明,在資源受限的情況下,無法準(zhǔn)確預(yù)測程序會(huì)死于哪種具體的原因。所以在這類錯(cuò)誤面前,不能綁死某種特定的錯(cuò)誤處理順序。
有的人在解決 “java.lang.OutOfMemoryError: GC overhead limit exceeded” 錯(cuò)誤時(shí),配置了下面的啟動(dòng)參數(shù):
我告訴你,這是一種完全錯(cuò)誤的做法。因?yàn)?UseGCOverheadLimit 這樣使用并不能真正地解決問題,只能推遲一點(diǎn) out of memory 錯(cuò)誤發(fā)生的時(shí)間,到最后還得進(jìn)行其他處理。指定這個(gè)選項(xiàng),會(huì)將原來的 java.lang.OutOfMemoryError: GC overhead limit exceeded 錯(cuò)誤掩蓋,變成更常見的 java.lang.OutOfMemoryError: Java heap space 錯(cuò)誤消息。
有時(shí)候觸發(fā) GC overhead limit 錯(cuò)誤的原因, 是因?yàn)榉峙浣oJVM的堆內(nèi)存不足。這種情況下只需要增加堆內(nèi)存大小即可。
在大多數(shù)情況下, 增加堆內(nèi)存并不能解決問題。例如程序中存在內(nèi)存泄漏, 增加堆內(nèi)存只能推遲產(chǎn)生 java.lang.OutOfMemoryError: Java heap space 錯(cuò)誤的時(shí)間。
看完上述內(nèi)容,你們掌握如何理解JVM的GC overhead limit exceeded錯(cuò)誤的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。