java內存溢出和內存泄漏

基本上任何面試都會涉及到的問題,只要問到關于內存的問題,肯定會問一下這個問題,所以今天專門來說一下關于內存溢出的問題


1.概念

首先我們要知道什么是內存溢出,不要和內存泄漏搞混了,內存溢出是指程序在為自身申請內存時,沒有足夠的內存空間供自己使用,內存溢出通常發(fā)生于OLD段或Perm段垃圾回收后,仍然無內存空間容納新的Java對象的情況,進而出現out of memory,內存泄漏是指那些本應該回收(不再使用)的內存對象無法被系統(tǒng)回收的現象。

2.為什么需要了解這些東西呢?

1.通過了解內存溢出的幾種常見情況,可以在出現內存溢出的時候快速的定位問題的位置,縮短解決故障的時間。

2.內存泄露一般是代碼設計存在缺陷導致的,通過了解內存泄露的場景,可以避免不必要的內存溢出和提高自己的代碼編寫水平;

從定義上可以看出內存泄露是內存溢出的一種誘因,不是唯一因素。

3.內存泄漏的場景

a.長生命周期的對象持有短生命周期對象的引用,這是內存泄漏最常見的場景,也是代碼設計的時候最常見的問題,比如在全局靜態(tài)map中緩存局部變量,并且沒有清空的操作,那么隨著時間的推移,這個map會越來越大,造成內存泄漏。

b.修改hashset中對象的參數值,并且參數是計算哈希值的字段,當一個對象被存儲進HashSet集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段,否則對象修改后的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作為參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中刪除當前對象,造成內存泄露

4.內存溢出的情況

1.堆內存溢出(outOfMemoryError:java heap space

在jvm規(guī)范中,堆中的內存是用來生成對象實例和數組的。

? ? ? ?如果細分,堆內存還可以分為年輕代和年老代,年輕代包括一個eden區(qū)和兩個survivor區(qū)。

? ? ? ?當生成新對象時,內存的申請過程如下:

? ? ? ? ? a、jvm先嘗試在eden區(qū)分配新建對象所需的內存;

? ? ? ? ? b、如果內存大小足夠,申請結束,否則下一步;

? ? ? ? ? c、jvm啟動youngGC,試圖將eden區(qū)中不活躍的對象釋放掉,釋放后若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區(qū);

? ? ? ? ? d、Survivor區(qū)被用來作為Eden及old的中間交換區(qū)域,當OLD區(qū)空間足夠時,Survivor區(qū)的對象會被移到Old區(qū),否則會被保留在Survivor區(qū);

? ? ? ? ? e、?當OLD區(qū)空間不夠時,JVM會在OLD區(qū)進行full GC;

? ? ? ? ? f、full GC后,若Survivor及OLD區(qū)仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區(qū)為新對象創(chuàng)建內存區(qū)域,則出現”out of memory錯誤”:

2.方法區(qū)內存溢出(outOfMemoryError:permgem space

在jvm規(guī)范中,方法區(qū)主要存放的是類信息、常量、靜態(tài)變量等。所以如果程序加載的類過多,或者使用反射、gclib等這種動態(tài)代理生成類的技術,就可能導致該區(qū)發(fā)生內存溢出,一般該區(qū)發(fā)生內存溢出時的錯誤信息為:outOfMemoryError:permgem space。jvm參數:-XX:PermSize=2m -XX:MaxPermSize=2。比如是:將方法區(qū)的大小設置很低即可,在啟動加載類庫時就會出現內存不足的情況

3、線程棧溢出java.lang.StackOverflowError

線程棧時線程獨有的一塊內存結構,所以線程棧發(fā)生問題必定是某個線程運行時產生的錯誤。一般線程棧溢出是由于遞歸太深或方法調用層級過多導致的,發(fā)生棧溢出的錯誤信息為:java.lang.StackOverflowError

5.為了避免造成內存溢出所需要做的事情

1、盡早釋放無用對象的引用?

2、使用字符串處理,避免使用String,應大量使用StringBuffer,每一個String對象都得獨立占用內存一塊區(qū)域

?3、盡量少用靜態(tài)變量,因為靜態(tài)變量存放在永久代(方法區(qū)),永久代基本不參與垃圾回收?

4、避免在循環(huán)中創(chuàng)建對象?

5、開啟大型文件或從數據庫一次拿了太多的數據很容易造成內存溢出,所以在這些地方要大概計算一下數據量的最大值是多少,并且設定所需最小及最大的內存空間值。?





?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,894評論 0 11
  • 雖然jvm可以通過GC自動回收無用的內存,但是代碼不好的話仍然存在內存溢出(OOM)風險。 一、為什么要了解內存泄...
    lucode閱讀 316評論 0 0
  • 內存溢出和內存泄漏的區(qū)別 內存溢出:out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,...
    Aimerwhy閱讀 800評論 0 1
  • 轉載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,505評論 1 56
  • 傍晚時分,劉欣語氣略顯興奮地給我打電話。說有一朋友給她送了條四、五斤重的山溪魚。她不會做魚,一個人也吃不了這么多,...
    月兒上山了閱讀 475評論 42 25

友情鏈接更多精彩內容