摘要:內存溢出分配的內存空間超過系統內存。內存泄漏的原因分析由大塊組成堆,棧,本地方法棧,程序計數器,方法區。內存溢出的原因分析內存溢出是由于沒被引用的對象垃圾過多造成沒有及時回收,造成的內存溢出。小結棧內存溢出程序所要求的棧深度過大導致。
前言:JVM中除了程序計數器,其他的區域都有可能會發生內存溢出。0.什么是內存溢出
當程序需要申請內存的時候,由于沒有足夠的內存,此時就會拋出OutOfMemoryError,這就是內存溢出。
1.內存泄漏和內存溢出區別與聯系內存泄漏:系統分配的內存沒有被回收。
內存溢出:分配的內存空間超過系統內存。
2.內存泄漏的原因分析jvm由5大塊組成:堆,棧,本地方法棧,程序計數器,方法區。棧它的主要記錄方法的執行和對象的引用。堆則存在真正的引用的對象。
內存泄漏是由于使用不當,把一部分內存“丟掉了”,導致這部分內存不可用。
當在堆中創建了對象,后來沒有使用這個對象了,又沒有把整個對象的相關引用設為null。此時垃圾收集器會認為這個對象是需要的,就不會清理這部分內存。這就會導致這部分內存不可用。
所以內存泄漏會導致可用的內存減少,進而會導致內存溢出。
3. JVM垃圾回收機制思想就是從棧出發(root),遍歷對象的引用,在遍歷堆里面的引用對象,因為棧中的對象的引用執行完畢就刪除,所以我們就可以通過棧中的對象的引用,查找到堆中沒有被指向的對象,這些對象即為不可到達對象,對其進行垃圾回收。
4.內存溢出的原因分析內存溢出是由于沒被引用的對象(垃圾)過多造成JVM沒有及時回收,造成的內存溢出。如果出現這種現象可行代碼排查:
是否App中的類中和引用變量過多使用了Static修飾 如public staitc Student s;在類中的屬性中使用
static修飾的最好只用基本類型或字符串。如public static int i = 0; //public static
String str;
是否App中使用了大量的遞歸或無限遞歸(遞歸中用到了大量的建新的對象)
是否App中使用了大量循環或死循環(循環中用到了大量的新建的對象)
檢查App中是否使用了向數據庫查詢所有記錄的方法。即一次性全部查詢的方法,如果數據量超過10萬多條了,就可能會造成內存溢出。所以在查詢時應采用“分頁查詢”。
檢查是否有數組,List,Map中存放的是對象的引用而不是對象,因為這些引用會讓對應的對象不能被釋放。會大量存儲在內存中。
檢查是否使用了“非字面量字符串進行+”的操作。因為String類的內容是不可變的,每次運行"+"就會產生新的對象,如果過多會造成新String對象過多,從而導致JVM沒有及時回收而出現內存溢出。
如:
String s1 = "My name"; String s2 = "is"; String s3 = "xiaomanong"; String str = s1 + s2 + s3 +.........;
這是會容易造成內存溢出的
但是String str = "My name" + " is " + " xuwei" + " nice " + " to " + " meet you"; //但是這種就不會造成內存溢出。因為這是”字面量字符串“,在運行"+"時就會在編譯期間運行好。不會按照JVM來執行的。
在使用String,StringBuffer,StringBuilder時,如果是字面量字符串進行"+"時,應選用String性能更好;如果是String類進行"+"時,在不考慮線程安全時,應選用StringBuilder性能更好。
5.常見的四種內存溢出情況堆溢出(OutOfMemoryError:java heap space)
持久代溢出(OutOfMemoryError: PermGen space)
棧溢出(StackOverflowError)
OutOfMemoryError:unable to create native thread
1)堆溢出:JVM Heap :java.lang.OutOfMemoryError: Java heap space
JVM在啟動的時候會自動設置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。Heap的大小是Young Generation 和Tenured Generaion 之和。在JVM中如果98%的時間是用于GC,且可用的Heap size 不足2%的時候將拋出此異常信息。
解決方法 :手動設置JVM Heap(堆)的大小。
2)持久代溢出:PermGen space : java.lang.OutOfMemoryError: PermGen space
PermGen space的全稱是Permanent Generation space,是指內存的永久保存區域。為什么會內存溢出,這是由于這塊內存主要是被JVM存放Class和Meta信息的,Class在被Load的時候被放入PermGen space區域,它和存放Instance的Heap區域不同,sun的 GC不會在主程序運行期對PermGen space進行清理,所以如果你的APP會載入很多CLASS的話,就很可能出現PermGen space溢出。一般發生在程序的啟動階段。
解決方法 : 通過-XX:PermSize和-XX:MaxPermSize設置永久代大小即可。
3)棧溢出: java.lang.StackOverflowError : Thread Stack space
棧溢出了,JVM依然是采用棧式的虛擬機,這個和C和Pascal都是一樣的。函數的調用過程都體現在堆棧和退棧上了。調用構造函數的 “層”太多了,以致于把棧區溢出了。 通常來講,一般棧區遠遠小于堆區的,因為函數調用過程往往不會多于上千層,而即便每個函數調用需要 1K的空間(這個大約相當于在一個C函數內聲明了256個int類型的變量),那么棧區也不過是需要1MB的空間。通常棧的大小是1-2MB的。通俗一點講就是單線程的程序需要的內存太大了。 通常遞歸也不要遞歸的層次過多,很容易溢出。
解決方法 :1:修改程序。2:通過 -Xss: 來設置每個線程的Stack大小即可。
4)OutOfMemoryError:unable to create native thread
OutOfMemoryError:unable to create native thread:字面意思是內存溢出:無法創建新的線程。字面意思已經很明顯了,出現這種情況的原因基本下面2點:
程序創建的線程數超過操作系統的限制。
JVM占用的內存太多,導致創建線程的內存空間太小。
我們都知道操作系統對每個進程的內存是有限制的,我們啟動Jvm,相當于啟動了一個進程,假如我們一個進程占用了4G的內存,那么通過下面的公式計算出來的剩余內存就是建立線程棧的時候可以用的內存。 線程棧總可用內存=4G-(-Xmx的值)- (-XX:MaxPermSize的值)- 程序計數器占用的內存 通過上面的公式我們可以看出,-Xmx 和 MaxPermSize的值越大,那么留給線程棧可用的空間就越小,在-Xss參數配置的棧容量不變的情況下,可以創建的線程數也就越小。因此如果是因為這種情況導致的unable to create native thread,
解決方法:1:增大進程所占用的總內存。2:減少-Xmx或者-Xss來達到創建更多線程的目的。
5)小結
棧內存溢出:程序所要求的棧深度過大導致。
堆內存溢出: 分清 內存泄露還是 內存容量不足。泄露則看對象如何被 GC Root 引用。不足則通過 調大 -Xms,-Xmx參數。
持久帶內存溢出:Class對象未被釋放,Class對象占用信息過多,有過多的Class對象。
無法創建本地線程:總容量不變,堆內存,非堆內存設置過大,會導致能給線程的內存不足。
下面哪種情況會導致持久區jvm堆內存溢出():
A. 循環上萬次的字符串處理
B. 在一段代碼內申請上百M甚至上G的內存
C. 使用CGLib技術直接操作字節碼運行,生成大量的動態類
D. 不斷創建對象
解答:AC
解析:AC是持久帶,B直接內存也就是堆外內存,D堆內存。
參考書籍:《深入理解Java虛擬機》 (第二版) 周志明 著;
溫馨提示: 如果你喜歡本文,并且想要學習更多干貨內容,可以關注一下我的公眾號《Java技術zhai》;
不定期的技術干貨內容分享,帶你重新理解架構的魅力!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76057.html
摘要:從使用到原理學習線程池關于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現在軟件開發中,分散于應用中多出的功能被稱為橫切關注點如事務安全緩存等。 Java 程序媛手把手教你設計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經風雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:而字節碼運行在之上,所以不用關心字節碼是在哪個操作系統編譯的,只要符合規范,那么,這個字節碼文件就是可運行的。好處防止內存中出現多份同樣的字節碼安全性角度特別說明類加載器在成功加載某個類之后,會把得到的類的實例緩存起來。 前言 只有光頭才能變強 JVM在準備面試的時候就有看了,一直沒時間寫筆記。現在到了一家公司實習,閑的時候就寫寫,刷刷JVM博客,刷刷電子書。 學習JVM的目的也很簡單...
摘要:方法區溢出在的方法區中,它主要存放了類的信息,常量,靜態變量等。運行結果簡單解決思路一般來說此類問題多出現在存在遞歸的地方,要從代碼里重新審視遞歸未結束的原因,若遞歸的方法沒問題可以根據實際情況調整參數的大小。 前言 如今不管是在面試還是在我們的工作中,OOM總是不斷的出現在我們的視野中,所以我們有必要去了解一下導致OOM的原因以及一些基本的調整方法,大家可以通過下面的事例來了解一下什...
閱讀 1076·2021-11-22 14:56
閱讀 1520·2019-08-30 15:55
閱讀 3359·2019-08-30 15:45
閱讀 1655·2019-08-30 13:03
閱讀 2868·2019-08-29 18:47
閱讀 3334·2019-08-29 11:09
閱讀 2641·2019-08-26 18:36
閱讀 2615·2019-08-26 13:55