版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
【情況一】:
Java.lang.OutOfMemoryError:Javaheap space:這種是java堆內(nèi)存不夠,一個原因是真不夠,另一個原因是程序中有死循環(huán);
如果是java堆內(nèi)存不夠的話,可以通過調(diào)整JVM下面的配置來解決:
< jvm-arg>-Xms3062m < / jvm-arg>
< jvm-arg>-Xmx3062m < / jvm-arg>
【情況二】
java.lang.OutOfMemoryError: GC overhead limit exceeded
【解釋】:JDK6新增錯誤類型,當GC為釋放很小空間占用大量時間時拋出;一般是因為堆太小,導(dǎo)致異常的原因,沒有足夠的內(nèi)存。
【解決方案】:
1、查看系統(tǒng)是否有使用大內(nèi)存的代碼或死循環(huán);
2、通過添加JVM配置,來限制使用內(nèi)存:
< jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg>
【情況三】:
java.lang.OutOfMemoryError: PermGen space:這種是P區(qū)內(nèi)存不夠,可通過調(diào)整JVM的配置:
< jvm-arg>-XX:MaxPermSize=128m< /jvm-arg>
< jvm-arg>-XXermSize=128m< /jvm-arg>
【注】:
JVM的Perm區(qū)主要用于存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space,這個區(qū)域成為年老代,GC在主程序運行期間不會對年老區(qū)進行清理,默認是64M大小,當程序需要加載的對象比較多時,超過64M就會報這部分內(nèi)存溢出了,需要加大內(nèi)存分配,一般128m足夠。
【情況四】:
java.lang.OutOfMemoryError: Direct buffer memory
調(diào)整-XX:MaxDirectMemorySize= 參數(shù),如添加JVM配置:
< jvm-arg>-XX:MaxDirectMemorySize=128m< /jvm-arg>
【情況五】:
java.lang.OutOfMemoryError: unable to create new native thread
【原因】:Stack空間不足以創(chuàng)建額外的線程,要么是創(chuàng)建的線程過多,要么是Stack空間確實小了。
【解決】:由于JVM沒有提供參數(shù)設(shè)置總的stack空間大小,但可以設(shè)置單個線程棧的大??;而系統(tǒng)的用戶空間一共是3G,除了Text/Data/BSS /MemoryMapping幾個段之外,Heap和Stack空間的總量有限,是此消彼長的。因此遇到這個錯誤,可以通過兩個途徑解決:
1.通過 -Xss啟動參數(shù)減少單個線程棧大小,這樣便能開更多線程(當然不能太小,太小會出現(xiàn)StackOverflowError);
2.通過-Xms -Xmx 兩參數(shù)減少Heap大小,將內(nèi)存讓給Stack(前提是保證Heap空間夠用)。
【情況六】:
java.lang.StackOverflowError
【原因】:這也內(nèi)存溢出錯誤的一種,即線程棧的溢出,要么是方法調(diào)用層次過多(比如存在無限遞歸調(diào)用),要么是線程棧太小。
【解決】:優(yōu)化程序設(shè)計,減少方法調(diào)用層次;調(diào)整-Xss參數(shù)增加線程棧大小。
Throwable
Throwable是 Java 語言中所有錯誤或異常的超類。
Throwable包含兩個子類: Error 和 Exception 。它們通常用于指示發(fā)生了異常情況。
Throwable包含了其線程創(chuàng)建時線程執(zhí)行堆棧的快照,它提供了printStackTrace()等接口用于獲取堆棧跟蹤數(shù)據(jù)等信息。
Exception
Exception及其子類是 Throwable 的一種形式,它指出了合理的應(yīng)用程序想要捕獲的條件。
RuntimeException
RuntimeException是那些可能在 Java 虛擬機正常運行期間拋出的異常的超類。
編譯器不會檢查RuntimeException異常。例如,除數(shù)為零時,拋出ArithmeticException異常。RuntimeException是ArithmeticException的超類。當代碼發(fā)生除數(shù)為零的情況時,倘若既”沒有通過throws聲明拋出ArithmeticException異?!?,也”沒有通過try…catch…處理該異?!保材芡ㄟ^編譯。這就是我們所說的”編譯器不會檢查RuntimeException異?!?!
如果代碼會產(chǎn)生RuntimeException異常,則需要通過修改代碼進行避免。 例如,若會發(fā)生除數(shù)為零的情況,則需要通過代碼避免該情況的發(fā)生!
Error
和Exception一樣, Error也是Throwable的子類。 它用于指示合理的應(yīng)用程序不應(yīng)該試圖捕獲的嚴重問題,大多數(shù)這樣的錯誤都是異常條件。
和RuntimeException一樣,編譯器也不會檢查Error。
Java將可拋出(Throwable)的結(jié)構(gòu)分為三種類型:被檢查的異常(Checked Exception),運行時異常(RuntimeException)和錯誤(Error)。
(01) 運行時異常
定義 : RuntimeException及其子類都被稱為運行時異常。
特點 :Java編譯器不會檢查它。 也就是說,當程序中可能出現(xiàn)這類異常時,倘若既”沒有通過throws聲明拋出它”,也”沒有用try-catch語句捕獲它”,還是會編譯通過。例如,除數(shù)為零時產(chǎn)生的ArithmeticException異常,數(shù)組越界時產(chǎn)生的IndexOutOfBoundsException異常,fail-fail機制產(chǎn)生的ConcurrentModificationException異常等,都屬于運行時異常。
雖然Java編譯器不會檢查運行時異常,但是我們也可以通過throws進行聲明拋出,也可以通過try-catch對它進行捕獲處理。
如果產(chǎn)生運行時異常,則需要通過修改代碼來進行避免。 例如,若會發(fā)生除數(shù)為零的情況,則需要通過代碼避免該情況的發(fā)生!
(02) 被檢查的異常
定義 :? Exception類本身,以及Exception的子類中除了”運行時異?!敝獾钠渌宇惗紝儆诒粰z查異常。
特點 :Java編譯器會檢查它。此類異常,要么通過throws進行聲明拋出,要么通過try-catch進行捕獲處理,否則不能通過編譯。例如,CloneNotSupportedException就屬于被檢查異常。當通過clone()接口去克隆一個對象,而該對象對應(yīng)的類沒有實現(xiàn)Cloneable接口,就會拋出CloneNotSupportedException異常。
被檢查異常通常都是可以恢復(fù)的。
(03) 錯誤
定義 : Error類及其子類。
特點 : 和運行時異常一樣,編譯器也不會對錯誤進行檢查。
當資源不足、約束失敗、或是其它程序無法繼續(xù)運行的條件發(fā)生時,就產(chǎn)生錯誤。程序本身無法修復(fù)這些錯誤的。例如,VirtualMachineError就屬于錯誤。
按照Java慣例,我們是不應(yīng)該是實現(xiàn)任何新的Error子類的!
對于上面的3種結(jié)構(gòu),我們在拋出異?;蝈e誤時,到底該哪一種?《Effective Java》中給出的建議是:對于可以恢復(fù)的條件使用被檢查異常,對于程序錯誤使用運行時異常。
1,? OutOfMemoryError異常
除了程序計數(shù)器外,虛擬機內(nèi)存的其他幾個運行時區(qū)域都有發(fā)生OutOfMemoryError(OOM)異常的可能,
javaHeap 溢出
一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存儲對象實例,我們只要不斷的創(chuàng)建對象,并且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數(shù)量達到最大堆容量限制后產(chǎn)生內(nèi)存溢出異常。
出現(xiàn)這種異常,一般手段是先通過內(nèi)存映像分析工具(如Eclipse Memory
Analyzer)對dump出來的堆轉(zhuǎn)存快照進行分析,重點是確認內(nèi)存中的對象是否是必要的,先分清是因為內(nèi)存泄漏(Memory
Leak)還是內(nèi)存溢出(Memory Overflow)。
如果是內(nèi)存泄漏,可進一步通過工具查看泄漏對象到GC Roots的引用鏈。于是就能找到泄漏對象時通過怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無法自動回收。
如果不存在泄漏,那就應(yīng)該檢查虛擬機的參數(shù)(-Xmx與-Xms)的設(shè)置是否適當。
2,? 虛擬機棧和本地方法棧溢出
如果線程請求的棧深度大于虛擬機所允許的最大深度,將拋出StackOverflowError異常。
如果虛擬機在擴展棧時無法申請到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常
這里需要注意當棧的大小越大可分配的線程數(shù)就越少。
3,? 運行時常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGen space
如果要向運行時常量池中添加內(nèi)容,最簡單的做法就是使用String.intern()這個Native方法。該方法的作用是:如果池中已經(jīng)包含一個等于此String的字符串,則返回代表池中這個字符串的String對象;否則,將此String對象包含的字符串添加到常量池中,并且返回此String對象的引用。由于常量池分配在方法區(qū)內(nèi),我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區(qū)的大小,從而間接限制其中常量池的容量。
4,? 方法區(qū)溢出
方法區(qū)用于存放Class的相關(guān)信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。
異常信息:java.lang.OutOfMemoryError:PermGen space
方法區(qū)溢出也是一種常見的內(nèi)存溢出異常,一個類如果要被垃圾收集器回收,判定條件是很苛刻的。在經(jīng)常動態(tài)生成大量Class的應(yīng)用中,要特別注意這點。