異常、堆記憶體溢位、OOM的幾種情況
堆記憶體溢位
【情況一】:
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為釋放很小空間佔用大量時間時丟擲;一般是因為堆太小,導致異常的原因,沒有足夠的記憶體。
【解決方案】:
1、檢視系統是否有使用大記憶體的程式碼或死迴圈;
2、通過新增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異常,則需要通過修改程式碼進行避免。 例如,若會發生除數為零的情況,則需要通過程式碼避免該情況的發生!
Error
和Exception一樣, Error也是Throwable的子類。 它用於指示合理的應用程式不應該試圖捕獲的嚴重問題,大多數這樣的錯誤都是異常條件。
和RuntimeException一樣, 編譯器也不會檢查Error。
Java將可丟擲(Throwable)的結構分為三種型別: 被檢查的異常(Checked Exception),執行時異常(RuntimeException)和錯誤(Error)。
(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子類的!
對於上面的3種結構,我們在丟擲異常或錯誤時,到底該哪一種?《Effective Java》中給出的建議是: 對於可以恢復的條件使用被檢查異常,對於程式錯誤使用執行時異常。
OOM
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的應用中,要特別注意這點。
感謝您的關注!可加QQ1群:135430763,QQ2群:454796847,QQ3群:187424846。QQ群進群密碼:xttblog,想加微信群的朋友,可以微信搜尋:xmtxtt,備註:“xttblog”,新增助理微信拉你進群。備註錯誤不會同意好友申請。再次感謝您的關注!後續有精彩內容會第一時間發給您!原創文章投稿請傳送至532009913@qq.com郵箱。商務合作可新增助理微信進行溝通!
相關文章
- Java記憶體溢位(OOM)異常完全指南Java記憶體溢位OOM
- Java記憶體溢位情況Java記憶體溢位
- java常見的幾種記憶體溢位和解決方案Java記憶體溢位
- JAVA記憶體區域與記憶體溢位異常Java記憶體溢位
- JVM(2)-Java記憶體區域與記憶體溢位異常JVMJava記憶體溢位
- JVM系列之實戰記憶體溢位異常JVM記憶體溢位
- 阿里大佬講解Java記憶體溢位示例(堆溢位、棧溢位)阿里Java記憶體溢位
- Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)RedisError記憶體溢位
- Java 常見記憶體溢位異常與程式碼實現Java記憶體溢位
- js引起記憶體洩露的幾種情況分析JS記憶體洩露
- Java記憶體區域與記憶體溢位異常(JVM學習系列1)Java記憶體溢位JVM
- 第二章 Java記憶體區域與記憶體溢位異常(1)Java記憶體溢位
- 【Java】幾種典型的記憶體溢位案例,都在這兒了!Java記憶體溢位
- Java記憶體區域與記憶體溢位異常 - 執行時資料區Java記憶體溢位
- Java棧溢位|記憶體洩漏|記憶體溢位Java記憶體溢位
- 記憶體溢位記憶體溢位
- [摘譯]js記憶體洩漏常見的四種情況JS記憶體
- 記憶體溢位的分析記憶體溢位
- 深入理解JVM讀書筆記一: Java記憶體區域與記憶體溢位異常JVM筆記Java記憶體溢位
- Java虛擬機器01——Java記憶體資料區域和記憶體溢位異常Java虛擬機記憶體溢位
- 深入理解Java虛擬機器-Java記憶體區域與記憶體溢位異常Java虛擬機記憶體溢位
- Java記憶體溢位Java記憶體溢位
- JBOSS記憶體溢位記憶體溢位
- 記憶體溢位:native溢位 和 上層溢位記憶體溢位
- Android載入圖片導致記憶體溢位(Out of Memory異常)Android記憶體溢位
- JVM記憶體區域以及各區域的記憶體溢位異常,記憶體分代策略,垃圾收集演算法,各種垃圾收集器JVM記憶體溢位演算法
- 用瀏覽器測試幾種閉包占用記憶體的情況瀏覽器記憶體
- 記憶體溢位的問題記憶體溢位
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- 記憶體洩漏和記憶體溢位記憶體溢位
- 05記憶體情況記憶體
- WebLogic: 記憶體溢位Web記憶體溢位
- java 程式記憶體溢位Java記憶體溢位
- 記憶體溢位問題記憶體溢位
- 從記憶體洩露、記憶體溢位和堆外記憶體,JVM優化引數配置引數記憶體洩露記憶體溢位JVM優化
- 手動寫java OOM記憶體溢位 java.lang.OutOfMemoryError: Java heap spaceJavaOOM記憶體溢位Error
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- 傳說中的記憶體溢位記憶體溢位