既然JVM有Full GC,為什麼還會出現OutOfMemoryError?
既然在觸發Full GC的時候,年老代和持久帶都會被清理,那麼為什麼還會出現OOM問題?而且,對於強引用,
當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足問題。那麼Full GC機制的存在有何意義(還是說F GC主要針對的是駐紮在年老代的軟引用)?既然如此,對於四種引用的方式如何抉擇?總不能所有對象都創建引用隊列使用軟引用或者弱引用吧~
這個問題的意思是:
「為什麼我請了傭人來收拾房間,我的房間還是會堆滿?那我還請傭人來幹什麼?他不是號稱能把我房間里的垃圾都清理乾淨的么?」問題是如果您房間里堆的都是寶貝(或者看起來都是寶貝)的話,傭人也沒轍啊。
怎麼判斷是不是寶貝呢?就看主人有沒有用手抓著它——被抓住的寶貝如果有連接到別的寶貝的話那被連接到的也算上。用力抓住的肯定是寶貝,一點沒碰的肯定不是寶貝,半抓不抓著的先觀望。謝謝 @Yaya Match邀請
在Java虛擬機規範中,將JVM內存分為程序計數器,Java虛擬機棧,本地方法棧,Java堆,方法區,運行時常量池(包含於方法區),直接內存(直接內存並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域,但是這部分內存也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現)除了程序計數器之外都是有可能出現OutOfMemoryError異常的。
下面舉例說明:Java堆用於存儲對象實例,我們只要不斷的創建對象,並且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數量到達最大堆的容量限制後產生內存溢出異常。@RednaxelaFX的答案更加生動----------------------本質上來講是FullGC來不及清理
好問題
如果你仔細看GC log 就會發現, full GC的時候,很少有把old gen全放光的情況。當系統頻繁full gc的時候,其實系統已經有oom的趨勢了。
我很喜歡看gc log,就像看人的自傳一樣,你一行行看,就知道這個系統在每分每秒的行為,非常有趣,建議你試試。
一個簡單的例子,你的堆只有100M,你new了一個101M的大數組,這時候神也幫不了你。
看名字 GC..噶備至 collection 打個比方,jvm現在還有 10mb內存可用,這時候你先讀了一個9mb的文件來,沒問題對吧。
之後你還沒有關閉這個資源。
jvm: 哦主人剛讀了一個9mb的文件,主人還沒說這東西不用..萬一回收了主人該責怪我了。。本寶寶不能回收樓主: 我還要讀一個10mb的文件。卧槽你怎麼報錯了,你的GC吃屎了么!考試的時候,你用鉛筆在一張答題紙上演算一道複雜的數學題,算著算著,就寫滿了整張紙(包括背面)。 我察,還沒算完,回頭看看有沒有能擦掉的地方,一看,所有地方的計算公式或者中間結果都是有用的,不然閱卷老師不給分。此時就是OOM, 你看(Full GC)一百遍也沒用。你只能向監考老師報告OOM:老師我沒紙了,再給我幾張。
不夠用就是不夠用,你怎麼回收也沒用啊。要是fgc那麼好使,那豈不是所有Java程序都只分配1kb的內存給他就夠了
虛擬機在執行FGC的時候會啟動一個回收線程並同時暫停其它線程的運行(沒記錯的話至少到Java8的Hotspot是這樣的吧?當然對於這個FGC線程可以佔用多少CPU時間等等是有很多參數可以調整的),假設當其它業務線程正在使用某老年代對象的過程中,這時來個FGC線程把老年代對象給清空了,等業務線程恢復運行時發現指針已經成NULL了,那豈不成了滿屏的空指針異常了……
GC回收的是無用的部分,如果裡面都是你正在使用的東西,那麼GC並不會把這些回收掉。但是在內存緊張的情況下,你還需要內存,不夠用了,自然就是OutOfMemoryError了。輕噴...
題主需要稍微了解下《java內存模型》
就像把大象放進冰箱,GC已經幫你把冰箱騰空了,可是冰箱里還是放不下大象,然後就OOM了
不是清理就一定清理出空間的,有用的對象是不能清理掉的。 內存不夠就是不夠。
fullgc只是把所有不被使用的對象清除而已,如果所有的對象都被使用,那就無法回收了
一個是垃圾,一個是大胖子,內存裝不下了。假如你是個胖子,說你是個垃圾,怎麼罵人呢??
你媽媽有打掃房間的習慣,可你家總會有亂糟糟的樣子,如果還喜歡收破爛,那麻煩了,屋子好不好一刻鐘就放滿了
full gc收集的是垃圾,及不可用的東西,如果對內存中的對象大部分是可達的,而此時又有新的對象需要分配內存空間,如果此時可用空間不夠就會OOM。
這問題小學的時候不就解釋過了嗎。一個水槽,A水管5分鐘注滿水槽,B水管10分鐘能將水槽的水放空,問:兩水管同時開啟,水槽會怎麼樣呢?
推薦閱讀:
※當jvm的eden區滿了,進行回收時,s0區滿了,此時eden區還有存活對象沒複製完,會怎樣?
※Go1.6中的gc pause已經完全超越JVM了嗎?
※問下, C++ 的垃圾回收機制 如何實現的話 要怎麼掃描 bss data 之類的欄位?
※XMLHttpRequest對象的生命周期是如何管理的?
※為什麼 C++ 11 標準不加入 GC 功能呢?
TAG:Java | Java虛擬機JVM | GC垃圾回收計算機科學 |