JVM的OOM分為多種狀況,下面會(huì)針對(duì)java.lang.OutOfMemoryError:Javaheapspace這種狀況解說(shuō)一下產(chǎn)生的原因與解決方案。
在JAVA運(yùn)用啟動(dòng)時(shí),會(huì)限制運(yùn)用的運(yùn)用空間。也就說(shuō),任何一個(gè)JAVA運(yùn)用,都只能運(yùn)用有限的內(nèi)存空間。
JAVA的內(nèi)存空間在JDK7及曾經(jīng)劃分為堆與永久代。在JDK8之后移除了永久代,選用元空間來(lái)代替。
在啟動(dòng)時(shí),經(jīng)過(guò)指定JVM參數(shù):`-Xmx`來(lái)設(shè)置可運(yùn)用的最大堆巨細(xì)。假如沒(méi)有顯式的設(shè)置,則體系上默認(rèn)為物理內(nèi)存的1/4(根據(jù)物理內(nèi)存的不同狀況有不同的分配規(guī)則??墒潜榧澳軌蛘J(rèn)為是1/4)。
產(chǎn)生java.lang.OutOfMemoryError:Javaheapspace異常時(shí),代表著運(yùn)用測(cè)驗(yàn)從堆上請(qǐng)求一個(gè)區(qū)域時(shí),堆沒(méi)有可配的空間。(注:可能有可運(yùn)用的物理內(nèi)存,可是沒(méi)有已經(jīng)達(dá)到了JAVA運(yùn)用可分配的內(nèi)存巨細(xì))
JVM是很智能的,在即將產(chǎn)生OOM時(shí),會(huì)進(jìn)行一次FullGC以收回可收回的目標(biāo)來(lái)開(kāi)釋空間。假如FullGC之后仍是沒(méi)有可滿足巨細(xì)的空間分配,才拋出java.lang.OutOfMemoryError:Javaheapspace。
java.lang.OutOfMemoryError:Javaheapspace正常是怎么產(chǎn)生的呢?
突發(fā)高峰期:程序在正常的用戶(hù)量和必定數(shù)據(jù)量時(shí)運(yùn)行正常??墒牵谀硞€(gè)高峰時(shí)導(dǎo)致超出預(yù)期閾值,內(nèi)存存活目標(biāo)運(yùn)用空間的量超出最大堆,并且無(wú)法收回。內(nèi)存走漏:由于編程錯(cuò)誤導(dǎo)致運(yùn)用程序不再需求的目標(biāo)(數(shù)據(jù))一直被持有引證,導(dǎo)致無(wú)法被收回。隨著時(shí)刻的推移,走漏的內(nèi)存目標(biāo)占用了一切的可用堆空間。分配合理的足夠內(nèi)存
最簡(jiǎn)略的解決方法就給JVM分配足夠大的內(nèi)存來(lái)滿足運(yùn)行程序的需求。
可是,需求注意在內(nèi)存泄漏的狀況下,分配再大的內(nèi)存也只是推遲了java.lang.OutOfMemoryError:Javaheapspace的產(chǎn)生。
并且,加大了JVM堆內(nèi)存,也會(huì)增加在GC時(shí)的暫停時(shí)刻(STW),影響程序的吞吐量,增加推遲。
怎么分配一個(gè)合理的內(nèi)存空間,是需求針對(duì)GC進(jìn)行優(yōu)化的。也就是常說(shuō)的JVM調(diào)優(yōu)。JVM調(diào)優(yōu)能夠參考:「JVM」GC——調(diào)優(yōu)介紹
那么,怎么調(diào)整經(jīng)過(guò)分配JAVA堆空間來(lái)解決問(wèn)題呢?
首先,需求了解以下這些問(wèn)題:
哪些目標(biāo)占用了很多的堆空間在哪些代碼中創(chuàng)建了這些目標(biāo)上述的問(wèn)題能夠經(jīng)過(guò)JVM自身的jmap來(lái)dump出運(yùn)行時(shí)的倉(cāng)庫(kù)信息。然后經(jīng)過(guò)如:MAT,JProfiler,jconsole等空間來(lái)進(jìn)行內(nèi)存目標(biāo)占用的跟蹤。
MAT運(yùn)用能夠參考:[JVM]MAT進(jìn)階運(yùn)用
當(dāng)然,這種方法是比較原始的方法。建議經(jīng)過(guò)如:Plumbr等JVM監(jiān)控工具來(lái)跟蹤問(wèn)題。
Plumbr的陳述信息
以上圖的監(jiān)控舉例扼要闡明一下怎么適當(dāng)?shù)倪M(jìn)行堆空間的巨細(xì)分配。
上圖所示中,能夠得到如下信息:
一切相關(guān)目標(biāo)的整個(gè)GCRoot引證內(nèi)存消耗最多的目標(biāo):
這些目標(biāo)在代碼中的分配位置:
根據(jù)上述的信息,咱們能夠得到這樣的猜想:
這個(gè)程序的需求的運(yùn)行空間超過(guò)248MB,并且是無(wú)法在必定時(shí)刻內(nèi)開(kāi)釋被收回。那么,按JVM調(diào)優(yōu)的思路,建議分配的最大堆巨細(xì)為:老時(shí)代活躍數(shù)據(jù)巨細(xì)*3~4倍。
所以,咱們第一次調(diào)整時(shí),能夠分配:248*4=992。
由于堆巨細(xì)的無(wú)法承認(rèn),所以第一次調(diào)整直接調(diào)整為:-Xmx1024m。
java內(nèi)存溢出的幾種原因和解決方案是什么?
java內(nèi)存溢出的幾種原因和解決方案如下。
第一種類(lèi)型的內(nèi)存溢出也被認(rèn)為是最多的。第一個(gè)反應(yīng)認(rèn)為是內(nèi)存溢出。倉(cāng)庫(kù)溢出。
什么狀況是倉(cāng)庫(kù)溢出呢?當(dāng)我看到下一個(gè)關(guān)鍵詞時(shí),鯉魚(yú)山水充滿了堆疊。
Java.lang.outofmemoryerror:javaheapspace.
也就是說(shuō),當(dāng)鯉魚(yú)山水看到heap關(guān)聯(lián)時(shí),一定會(huì)溢出倉(cāng)庫(kù)。此刻,假如代碼沒(méi)有問(wèn)題,適當(dāng)調(diào)整-Xmx和-Xms就能夠防止,但一定是代碼沒(méi)有問(wèn)題的前提。為什么會(huì)溢出來(lái)?代碼有問(wèn)題,或許拜訪次數(shù)太多,每次拜訪的時(shí)刻太長(zhǎng),或許數(shù)據(jù)太多,無(wú)法開(kāi)釋數(shù)據(jù)。因?yàn)槔栈仄鲿?huì)發(fā)現(xiàn)它們是垃圾收回器,因此在此處出現(xiàn)不認(rèn)為是這些東西的主意之前,體系可能會(huì)事先陳述過(guò)錯(cuò)的關(guān)鍵字。
ava.lang.outofmemoryerror3360gcoverheadlimitexceeded
假如體系處于高頻GC狀況,并且收回效果仍然很差,這將開(kāi)端陳述此過(guò)錯(cuò)。在這種狀況下,一般來(lái)說(shuō),可能會(huì)產(chǎn)生許多不應(yīng)開(kāi)釋的目標(biāo)。這是因?yàn)橐C運(yùn)用不當(dāng)和大型目標(biāo)請(qǐng)求導(dǎo)致的,但javaheapspace內(nèi)存溢出可能不會(huì)提早陳述此過(guò)錯(cuò)。這意味著內(nèi)存不足是直接原因,可能不是高頻GC。
類(lèi)型2的內(nèi)存溢出、PermGen溢出或PermGen已滿的提示,能夠看到類(lèi)似以下內(nèi)容的關(guān)鍵字:
重要的信息是:
Java.lang.outofmemoryerror:permgenspace
原因:體系代碼十分多、引證的第三方十分多、代碼中運(yùn)用了很多常量、在內(nèi)部注入常量、動(dòng)態(tài)代碼加載等辦法導(dǎo)致常量池膨脹。JDK1.5今后能夠通過(guò)設(shè)置收回永久譜帶,這里不做GC也足夠了,所以一般本年很少做同樣的操作,所以面對(duì)這種狀況常常運(yùn)用
類(lèi)型3的內(nèi)存溢出:在運(yùn)用ByteBuffer的allocateDirect()()時(shí)運(yùn)用,在許多javaNIO結(jié)構(gòu)中將其封裝為單獨(dú)的辦法
溢出關(guān)鍵字:
Java.lang.outofmemoryerror:directbuffermemory
假如直接或直接運(yùn)用ByteBuffer的allocateDirect辦法,假如不運(yùn)用clear,則會(huì)出現(xiàn)同樣的問(wèn)題。一般的參考程序IO輸出包括直接內(nèi)存和非直接內(nèi)存對(duì)應(yīng)的內(nèi)核狀況和用戶(hù)狀況的轉(zhuǎn)化進(jìn)程。一般的APP使用要將文件內(nèi)容輸出到客戶(hù)端,需求通過(guò)OS的直接內(nèi)存轉(zhuǎn)化復(fù)制到程序的非直接內(nèi)存,也就是heap直接內(nèi)存由操作體系和APP使用程序一起辦理,直接內(nèi)存不是APP使用程序能夠直接控制的內(nèi)存。請(qǐng)注意,jvm垃圾收回不會(huì)直接收回內(nèi)存部分的內(nèi)存。
假如有十分相似的操作,請(qǐng)考慮設(shè)置參數(shù)。-XX:MaxDirectMemorySize
類(lèi)型4內(nèi)存溢出過(guò)錯(cuò):
溢出關(guān)鍵字:
java.lang.StackOverflowError
此參數(shù)直接表明-Xss太小。我請(qǐng)求了許多本地調(diào)用的倉(cāng)庫(kù)引腳等內(nèi)容存儲(chǔ)在用戶(hù)現(xiàn)在具有的線程中。在jdk1.4之前,線程缺省為256K,在1.5之后為1M。假如陳述這個(gè)過(guò)錯(cuò),只能說(shuō)明-Xss太小了。當(dāng)然,一些制造商的JVM不是這個(gè)參數(shù)。本文只針對(duì)HotspotVM??墒?,您能夠根據(jù)需求優(yōu)化體系,以使-Xss的值可用。
第五類(lèi)內(nèi)存溢出過(guò)錯(cuò):
溢出關(guān)鍵字:
Java.lang.outofmemoryerror3360unabletocreatenewnativethread
上面第4個(gè)溢出過(guò)錯(cuò),說(shuō)明晰線程的內(nèi)存區(qū)域,但實(shí)際上線程基本上只占用了heap以外的內(nèi)存區(qū)域。也就是說(shuō),該過(guò)錯(cuò)表明在heap以外的區(qū)域中,不能向線程分配內(nèi)存區(qū)域。這解釋了是內(nèi)存本身不夠,仍是把heap的區(qū)域設(shè)定得太大,剩余的內(nèi)存變少了,仍是線程本身因?yàn)檎加脙?nèi)存而不夠了,其理由
第6類(lèi)內(nèi)存溢出:
溢出關(guān)鍵字
Java.lang.outofmemoryerror3360request{}bytefor{}outofswap
出現(xiàn)這種過(guò)錯(cuò)一般是因?yàn)榈刂房臻g不足。
六種常見(jiàn)的溢出顯現(xiàn)了99%的JVM溢出。擺脫這些溢出是十分困難的。可是,除非產(chǎn)生十分古怪的毛病,例如物理內(nèi)存硬件問(wèn)題導(dǎo)致codecache過(guò)錯(cuò),否則在這種狀況下內(nèi)存會(huì)直接落入crash中。同樣,內(nèi)存也能夠轉(zhuǎn)化為nativecode。因?yàn)閬y用JNI會(huì)導(dǎo)致無(wú)法開(kāi)釋本地內(nèi)存的問(wèn)題,因此請(qǐng)盡量防止運(yùn)用JNI。ioexception:toomanyon也會(huì)導(dǎo)致套接字連接數(shù)據(jù)打開(kāi)過(guò)多
廣州天河區(qū)珠江新城富力盈力大廈北塔2706
020-38013166(網(wǎng)站咨詢(xún)專(zhuān)線)
400-001-5281 (售后服務(wù)熱線)
深圳市坂田十二橡樹(shù)莊園F1-7棟
Site/ http://www.szciya.com
E-mail/ itciya@vip.163.com
品牌服務(wù)專(zhuān)線:400-001-5281
長(zhǎng)沙市天心區(qū)芙蓉中路三段398號(hào)新時(shí)空大廈5樓
聯(lián)系電話/ (+86 0731)88282200
品牌服務(wù)專(zhuān)線/ 400-966-8830
旗下運(yùn)營(yíng)網(wǎng)站:
Copyright ? 2016 廣州思洋文化傳播有限公司,保留所有權(quán)利。 粵ICP備09033321號(hào)