最近在使用 tomcat 的時(shí)候,總是在shutdown出現(xiàn)error='Cannot allocate memory' (errno=12)錯(cuò)誤碉熄。起初只當(dāng)是偶然因素引起的暇番,所以沒(méi)有重視崩哩。可是后來(lái)發(fā)現(xiàn)每次都會(huì)出現(xiàn)這個(gè)錯(cuò)誤戏自,所以這次決心找到原因解決邦投。
第一步
首先觀察報(bào)錯(cuò)信息如下:
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000eaaa0000, 357957632, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 357957632 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /home/gaea/tomcat-api/hs_err_pid14638.log
看#里面的內(nèi)容,主要表達(dá):Java 運(yùn)行所需內(nèi)存不足擅笔,本地內(nèi)存分配為提交保留的內(nèi)存分配失敗志衣。看到這里猛们,突然想到之前在 catalinn.sh 中更改過(guò)虛擬機(jī)的啟動(dòng)參數(shù)念脯,如下:
JAVA_OPTS="-Xms512m -Xmx1024m -Xss1024K"
第二步
分析錯(cuò)誤信息:
- 眾所周知,-Xms 表示堆的大小弯淘,-Xmx 表示堆的最大值绿店。當(dāng) Java 虛擬機(jī)的堆內(nèi)存不夠時(shí),就會(huì)向操作系統(tǒng)請(qǐng)求保留的堆內(nèi)存庐橙,即堆的最大值與當(dāng)前堆大小的差值假勿。這樣設(shè)置的目的是為了讓虛擬機(jī)有更好性能收縮彈性,但是在這里適得其反了态鳖,因?yàn)楫?dāng)前 tomcat 運(yùn)行的主機(jī)內(nèi)存為 2GB转培。除了tomcat 之外,系統(tǒng)中還運(yùn)行著其他服務(wù)浆竭,這就導(dǎo)致在 Java 虛擬機(jī)向操作系統(tǒng)請(qǐng)求分配保留的堆內(nèi)存時(shí)浸须,系統(tǒng)無(wú)法分配。
- 這里就引出了第二個(gè)問(wèn)題邦泄,為什么只是shutdown的時(shí)候才出現(xiàn)報(bào)錯(cuò)删窒,而 tomcat 沒(méi)有宕掉。這是因?yàn)樵趕hutdown時(shí)顺囊,需要單獨(dú)一個(gè)進(jìn)程來(lái)運(yùn)行關(guān)閉tomcat時(shí)的一些操作易稠,所以需要更多的內(nèi)存,恰恰這些需要分配的內(nèi)存超過(guò)了本地內(nèi)存的上限包蓝,導(dǎo)致分配失敗驶社。所謂『壓死駱駝的最后一根稻草』。
第三步
既然知道了問(wèn)題的原因测萎,解決起來(lái)就比較方便了亡电,直接在 catalina.sh 中將虛擬機(jī)啟動(dòng)參數(shù)修改如下:
JAVA_OPTS="-Xms512m -Xmx512m -Xss1024K"
這樣就解決問(wèn)題了。
思考
通過(guò)上訴問(wèn)題的解決硅瞧,可以得出結(jié)論:
- 不要在內(nèi)存吃緊的情況下份乒,采用 -Xmx的方式動(dòng)態(tài)分配堆內(nèi)存。
版權(quán)聲明:本文為博主原創(chuàng)文章腕唧,未經(jīng)博主允許不得轉(zhuǎn)載或辖。
http://www.reibang.com/p/08ca8dc4b5f0