JVM調(diào)優(yōu),首先應(yīng)從內(nèi)存開始,尤其是在真正的的web服務(wù)部署的時候。因為真正的web服務(wù)會比開發(fā)的時候花費更多的內(nèi)存,用來處理多用戶并發(fā)的情況。本人多次吃過這方面的虧,所以整理一下,希望能給別人以幫助。
這個年頭變啦,內(nèi)存變得如大白菜,每個新裝的機器都2G以上的內(nèi)存,甚至4G,也不是什么新聞。而軟件‘吃’內(nèi)存的情況則變化不大(除了VIsta)。但 JAVA誕生的時候可不是這樣——95年,想來當年97年,64M的內(nèi)存還要500元,所以JVM初始化對內(nèi)存的要不能太大,而且也要考慮老機器的情況,畢竟現(xiàn)在JRE基本跑在每個人的機器上。但是JVM初始占用還停留在幾年前的情況下,確實沒有跟上軟件和硬件的發(fā)展。而像Tomcat, JBoss, Eclipse(尤其安上MyEclipse插件后),也考慮到每臺機器的內(nèi)存情況,所以初始話定義都很低,經(jīng)常會拋內(nèi)存溢出Bug。
好,言歸正傳。我們先從解決bug開始,當Java程序申請內(nèi)存,超出VM可分配內(nèi)純的時候,VM首先可能會GC,如果GC完還是不夠,或者申請的直接超夠VM可能有的,就會拋出內(nèi)存溢出異常。從VM規(guī)范中我們可以得到,一下幾種異常。
java.lang.StackOverflowError:(很少)
java.lang.OutOfMemoryError:heap space(比較常見)
java.lang.OutOfMemoryError: PermGen space (經(jīng)常出現(xiàn))
以下分別解釋一下,從最常見的開始:
java.lang.OutOfMemoryError: PermGen space這個異常比較常見,是說JVM里的Perm內(nèi)存區(qū)的異常溢出,由于JVM在默認的情況下,Perm默認為64M,而很多程序需要大量的Perm區(qū)內(nèi)存,尤其使用到像Spring等框架的時候,由于需要使用到動態(tài)生成類,而這些類不能被GC自動釋放,所以導致OutOfMemoryError: PermGen space異常。解決方法很簡單,增大JVM的 -XX:MaxPermSize 啟動參數(shù),就可以解決這個問題,如過使用的是默認變量通常是64M[5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.],改成128M就可以了,-XX:MaxPermSize=128m。如果已經(jīng)是128m(Eclipse已經(jīng)是128m了),就改成 256m。我一般在服務(wù)器上為安全起見,改成256m。
java.lang.OutOfMemoryError:heap space或 其它OutOfMemoryError,這個異常實際上跟上面的異常是一個異常,但解決方法不同,所以分開來寫。上面那個異常是因為JVM的perm區(qū)內(nèi)存區(qū)分少了引起的(JVM的內(nèi)存區(qū)分為 young,old,perm三種)。而這個異常是因為JVM堆內(nèi)存或者說總體分少了。解決方法是更改 -Xms -Xmx 啟動參數(shù),通常是擴大1倍。xms是管理啟動時最小內(nèi)存量的,xmx是管里JVM最大的內(nèi)存量的。
注:OutOfMemoryError可能有很多種原因,根據(jù)JVM Specification, 可能有一下幾種情況,我先簡單列出。stack:stack分區(qū)不能動態(tài)擴展,或不足以生成新的線程。Heap:需要更多的內(nèi)存,而不能獲得。Method Area :如果不能滿足分配需求。runtime constant pool(從Method Area分配內(nèi)存)不足以創(chuàng)建class or interface。native method stacks不能夠動態(tài)擴展,或生成新的本地線程。
最后說說java.lang.StackOverflowError,老實說這個異常我也沒碰見過,但JVM Specification就提一下,規(guī)范上說有一下幾種境況可能拋出這個異常,一個是Stacks里的線程超過允許的時候,另一個是當native method要求更大的內(nèi)存,而超過native method允許的內(nèi)存的時候。根據(jù)SUN的文檔,提高-XX:ThreadStackSize=512的值。
總的來說調(diào)優(yōu)JVM的內(nèi)存,組要目的就是在使用內(nèi)存盡可能小的,使程序運行正常,不拋出內(nèi)純溢出的bug。而且要調(diào)好最小內(nèi)存,最大內(nèi)存的比,避免GC時浪費太多時間,尤其是要盡量避免FULL GC。