簡單的記憶體“洩露”和“溢位”

聆聽的車轍發表於2019-04-01

簡單的記憶體“洩露”和“溢位”

前言

小時候記得印象最喜歡的應該就是小智的卡比獸了。然而不論是金,銀還是其他版本中,卡比獸都好弱啊~~~不過,卡比獸的“記憶體”是真的大呢,好像永遠都不會溢位或者洩漏呢,等等,這什麼意思!!

記憶體溢位

解釋

所謂的記憶體溢位,從字面上的意思即jvm記憶體不夠用了,目前無法存放建立的物件。

原因

  1. JVM分配的記憶體相對較小,也許是機器的記憶體本來就小,也可以是jvm引數xmx設定的較小。
  2. 某段程式碼進行了死迴圈,導致物件瘋狂產生,但是又不會觸發GC,所以就記憶體溢位了。

public void 建立GC的方法(){
    List list = new ArrayList<>();
    while(true){
        Person p1 = new Person(); # p1變數總是指向不同的物件,應該會Gc
        p1.setAge("23");
        list.add(p1); # 但是list原理是陣列,又指向了建立的物件,導致無法GC
    }
}
其實這也能算是一種記憶體洩漏了。
複製程式碼
  1. 建立的物件太大,最典型的就是IO了。物件太大導致新生代存放不下,只能存放到老年代。而老年代也存放不下,只能OOM了。

解決(對應上述的解釋)

  1. 增大伺服器記憶體,設定xmxxms
  2. 這時候是一定會GC的,通過執行緒dump和堆dump。分析出現問題的程式碼
  3. 增大jvm記憶體,及時關閉流,及時GC。

記憶體洩露

解釋

不再會被使用的物件不能被回收,就是記憶體洩露。說的通俗點就是:該物件已經需要被GC了,卻沒有這麼做。

原因

看一段程式碼:

public class Simple {
    Object o1;
    public void method1(){
        o1 = new Object();
        //...其他程式碼
    }
在Simple的例項沒有被回收之前,object物件就不會被回收。原因就是因為o1是例項變數
複製程式碼

解決

public class Simple {
    Object o1;
    public void method1(){
        o1 = new Object();
        //...其他程式碼
        o1 = null
    }
不管是採用引用計數,或者是GC Root判斷是否應該GC,當o1 指向 null後,o1這個物件都會被GC
複製程式碼
public class Simple {
    public void method1(){
        Object o1 = new Object();
        //...其他程式碼
        o1 = null
    }
o1 的生命週期就只是這個方法了,所以o1這個物件將會被GC。
所以需要記住,設定例項變數時或者類變數 初始化時,想一下GC問題
複製程式碼

什麼是OOM

引用一段話:
OOM,全稱Out Of Memory,翻譯成中文就是“記憶體用完了”,來源於java.lang.OutOfMemoryError
看下關於的官方說明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.
意思就是說,當JVM因為沒有足夠的記憶體來為物件分配空間並且垃圾回收器也已經沒有空間可回收時,就會丟擲這個error(注:非exception,因為這個問題已經嚴重到不足以被應用處理)。

結語

記憶體溢位是一定會產生OOM的。而記憶體洩漏到達一定程度會導致記憶體溢位,產生OOM,如上述的list.add()。 參考自:連結

真羨慕卡比獸的肚子啊~~~

相關文章