【狀況一】:
Java.lang.OutOfMemoryError: Java heap space:這種是java堆內存不夠,一個緣由是真不夠,另外一個緣由是程序中有死循環;
若是是java堆內存不夠的話,能夠經過調整JVM下面的配置來解決:
< jvm-arg>-Xms3062m < / jvm-arg>
< jvm-arg>-Xmx3062m < / jvm-arg>
【狀況二】
java.lang.OutOfMemoryError: GC overhead limit exceeded
【解釋】:JDK6新增錯誤類型,當GC爲釋放很小空間佔用大量時間時拋出;通常是由於堆過小,致使異常的緣由,沒有足夠的內存。
【解決方案】:
一、查看系統是否有使用大內存的代碼或死循環;
二、經過添加JVM配置,來限制使用內存:
< jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg>
【狀況三】:
java.lang.OutOfMemoryError: PermGen space:這種是P區內存不夠,可經過調整JVM的配置:
< jvm-arg>-XX:MaxPermSize=128m< /jvm-arg>
< jvm-arg>-XXermSize=128m< /jvm-arg>
【注】:
JVM的Perm區主要用於存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space,這個區域成爲年老代,GC在主程序運行期間不會對年老區進行清理,默認是64M大小,當程序須要加載的對象比較多時,超過64M就會報這部份內存溢出了,須要加大內存分配,通常128m足夠。
【狀況四】:
java.lang.OutOfMemoryError: Direct buffer memory
調整-XX:MaxDirectMemorySize= 參數,如添加JVM配置:
< jvm-arg>-XX:MaxDirectMemorySize=128m< /jvm-arg>
【狀況五】:
java.lang.OutOfMemoryError: unable to create new native thread
【緣由】:Stack空間不足以建立額外的線程,要麼是建立的線程過多,要麼是Stack空間確實小了。
【解決】:因爲JVM沒有提供參數設置總的stack空間大小,但能夠設置單個線程棧的大小;而系統的用戶空間一共是3G,除了Text/Data/BSS /MemoryMapping幾個段以外,Heap和Stack空間的總量有限,是此消彼長的。所以遇到這個錯誤,能夠經過兩個途徑解決:
1.經過 -Xss啓動參數減小單個線程棧大小,這樣便能開更多線程(固然不能過小,過小會出現StackOverflowError);
2.經過-Xms -Xmx 兩參數減小Heap大小,將內存讓給Stack(前提是保證Heap空間夠用)。
【狀況六】:
java.lang.StackOverflowError
【緣由】:這也內存溢出錯誤的一種,即線程棧的溢出,要麼是方法調用層次過多(好比存在無限遞歸調用),要麼是線程棧過小。
【解決】:優化程序設計,減小方法調用層次;調整-Xss參數增長線程棧大小。java
Throwable
Throwable是 Java 語言中全部錯誤或異常的超類。
Throwable包含兩個子類: Error 和 Exception 。它們一般用於指示發生了異常狀況。
Throwable包含了其線程建立時線程執行堆棧的快照,它提供了printStackTrace()等接口用於獲取堆棧跟蹤數據等信息。數組
Exception
Exception及其子類是 Throwable 的一種形式,它指出了合理的應用程序想要捕獲的條件。多線程
RuntimeException
RuntimeException是那些可能在 Java 虛擬機正常運行期間拋出的異常的超類。
編譯器不會檢查RuntimeException異常。 例如,除數爲零時,拋出ArithmeticException異常。RuntimeException是ArithmeticException的超類。當代碼發生除數爲零的狀況時,假若既」沒有經過throws聲明拋出ArithmeticException異常」,也」沒有經過try…catch…處理該異常」,也能經過編譯。這就是咱們所說的」編譯器不會檢查RuntimeException異常」!
若是代碼會產生RuntimeException異常,則須要經過修改代碼進行避免。 例如,若會發生除數爲零的狀況,則須要經過代碼避免該狀況的發生!app
Error
和Exception同樣, Error也是Throwable的子類。 它用於指示合理的應用程序不該該試圖捕獲的嚴重問題,大多數這樣的錯誤都是異常條件。
和RuntimeException同樣, 編譯器也不會檢查Error。jvm
Java將可拋出(Throwable)的結構分爲三種類型: 被檢查的異常(Checked Exception),運行時異常(RuntimeException)和錯誤(Error)。ide
(01) 運行時異常
定義 : RuntimeException及其子類都被稱爲運行時異常。
特色 : Java編譯器不會檢查它。 也就是說,當程序中可能出現這類異常時,假若既」沒有經過throws聲明拋出它」,也」沒有用try-catch語句捕獲它」,仍是會編譯經過。例如,除數爲零時產生的ArithmeticException異常,數組越界時產生的IndexOutOfBoundsException異常,fail-fail機制產生的ConcurrentModificationException異常等,都屬於運行時異常。
雖然Java編譯器不會檢查運行時異常,可是咱們也能夠經過throws進行聲明拋出,也能夠經過try-catch對它進行捕獲處理。
若是產生運行時異常,則須要經過修改代碼來進行避免。 例如,若會發生除數爲零的狀況,則須要經過代碼避免該狀況的發生!工具
(02) 被檢查的異常
定義 : Exception類自己,以及Exception的子類中除了」運行時異常」以外的其它子類都屬於被檢查異常。
特色 : Java編譯器會檢查它。 此類異常,要麼經過throws進行聲明拋出,要麼經過try-catch進行捕獲處理,不然不能經過編譯。例如,CloneNotSupportedException就屬於被檢查異常。當經過clone()接口去克隆一個對象,而該對象對應的類沒有實現Cloneable接口,就會拋出CloneNotSupportedException異常。
被檢查異常一般都是能夠恢復的。優化
(03) 錯誤
定義 : Error類及其子類。
特色 : 和運行時異常同樣,編譯器也不會對錯誤進行檢查。
當資源不足、約束失敗、或是其它程序沒法繼續運行的條件發生時,就產生錯誤。程序自己沒法修復這些錯誤的。例如,VirtualMachineError就屬於錯誤。
按照Java慣例,咱們是不該該是實現任何新的Error子類的!spa
對於上面的3種結構,咱們在拋出異常或錯誤時,到底該哪種?《Effective Java》中給出的建議是: 對於能夠恢復的條件使用被檢查異常,對於程序錯誤使用運行時異常。線程
1, OutOfMemoryError異常
除了程序計數器外,虛擬機內存的其餘幾個運行時區域都有發生OutOfMemoryError(OOM)異常的可能,
Java Heap 溢出
通常的異常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用於存儲對象實例,咱們只要不斷的建立對象,而且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數量達到最大堆容量限制後產生內存溢出異常。
出現這種異常,通常手段是先經過內存映像分析工具(如Eclipse Memory Analyzer)對dump出來的堆轉存快照進行分析,重點是確認內存中的對象是不是必要的,先分清是由於內存泄漏(Memory Leak)仍是內存溢出(Memory Overflow)。
若是是內存泄漏,可進一步經過工具查看泄漏對象到GC Roots的引用鏈。因而就能找到泄漏對象時經過怎樣的路徑與GC Roots相關聯並致使垃圾收集器沒法自動回收。
若是不存在泄漏,那就應該檢查虛擬機的參數(-Xmx與-Xms)的設置是否適當。
2, 虛擬機棧和本地方法棧溢出
若是線程請求的棧深度大於虛擬機所容許的最大深度,將拋出StackOverflowError異常。
若是虛擬機在擴展棧時沒法申請到足夠的內存空間,則拋出OutOfMemoryError異常
這裏須要注意當棧的大小越大可分配的線程數就越少。
3, 運行時常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGen space
若是要向運行時常量池中添加內容,最簡單的作法就是使用String.intern()這個Native方法。該方法的做用是:若是池中已經包含一個等於此String的字符串,則返回表明池中這個字符串的String對象;不然,將此String對象包含的字符串添加到常量池中,而且返回此String對象的引用。因爲常量池分配在方法區內,咱們能夠經過-XX:PermSize和-XX:MaxPermSize限制方法區的大小,從而間接限制其中常量池的容量。
4, 方法區溢出
方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。
異常信息:java.lang.OutOfMemoryError:PermGen space
方法區溢出也是一種常見的內存溢出異常,一個類若是要被垃圾收集器回收,斷定條件是很苛刻的。在常常動態生成大量Class的應用中,要特別注意這點。