JVM內存機制資料筆記
參考
JDK5.0垃圾收集優化之--Don't Pause
http://blog.csdn.net/calvinxiu/archive/2007/05/18/1614473.aspx
JVM內存模型以及垃圾回收
http://hi.baidu.com/xuwanbest/blog/item/0587d82f2c44a73d1e30892e.html
對jvm內存的一些理解
http://www.blogjava.net/midstr/archive/2008/09/21/230292.html
了解JVM的內存管理與垃圾回收
http://hi.baidu.com/jiaozhenqing/blog/item/f18b85d4c1063a07a08bb77e.html
Java內存溢出的解決方案
http://hi.baidu.com/yanghlcn/blog/item/029e7303917b528dd43f7cc3.html
Java內存組成
?
?
堆(Heap)
??? 運行時數據區域,所有類實例和數組的內存均從此處分配。Java 虛擬機啟動時創建。對象的堆內存由稱為垃圾回收器 的自動內存管理系統回收。
??? 組成
??? ???
News Generation
(Young Generation即圖中的Eden + From Space + To Space)
??? ??? ???
Eden
存放新生的對象
??? ??? ???
Survivor Space
兩個 存放每次垃圾回收后存活的對象
??? ???
Old Generation
(Tenured Generation 即圖中的Old Space) 主要存放應用程序中生命周期長的存活對象
非堆內存
???
JVM具有一個由所有線程共享的方法區。方法區屬于非堆內存。它存儲每個類結構,如運行時常數池、字段和方法數據,以及方法和構造方法的代碼。它是在 Java 虛擬機啟動時創建的。
??? 除了方法區外,Java 虛擬機實現可能需要用于內部處理或優化的內存,這種內存也是非堆內存。 例如,JIT 編譯器需要內存來存儲從 Java 虛擬機代碼轉換而來的本機代碼,從而獲得高性能。
??? 組成
??? ???
Permanent Generation
?
(圖中的Permanent Space)
存放JVM自己的反射對象,比如類對象和方法對象
??? ???
native heap
GC策略
堆
????? JVM采用一種
分代回收
(generational collection) 的策略,用較高的頻率對年輕的對象(young generation)進行掃描和回收,這種叫做minor collection,而對老對象(old generation)的檢查回收頻率要低很多,稱為major collection。這樣就不需要每次GC都將內存中所有對象都檢查一遍。
????? 當一個URL被訪問時,
內存申請過程
如下:
A. JVM會試圖為相關Java對象在Eden中初始化一塊內存區域
B. 當Eden空間足夠時,內存申請結束。否則到下一步
C. JVM試圖釋放在Eden中所有不活躍的對象(這屬于1或更高級的垃圾回收), 釋放后若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區
D. Survivor區被用來作為Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,否則會被保留在Survivor區
E. 當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)
F. 完全垃圾收集后,若Survivor及OLD區仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區為新對象創建內存區域,則出現”out of memory錯誤”
???
對象衰老的過程
??? young generation的內存,由一塊Eden(伊甸園,有意思)和兩塊Survivor Space(1.4文檔中稱為semi-space)構成。新創建的對象的內存都分配自eden。兩塊Survivor Space總有會一塊是空閑的,用作copying collection的目標空間。Minor collection的過程就是將eden和在用survivor space中的活對象copy到空閑survivor space中。所謂survivor,也就是大部分對象在伊甸園出生后,根本活不過一次GC。對象在young generation里經歷了一定次數的minor collection后,年紀大了,就會被移到old generation中,稱為tenuring。(是否僅當survivor space不足的時候才會將老對象tenuring? 目前資料中沒有找到描述)
??? ?剩余內存空間不足會觸發GC,如eden空間不夠了就要進行minor collection,old generation空間不夠要進行major collection,permanent generation空間不足會引發full GC。
?
非堆內存
????? GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現PermGen space錯誤。
?
?
JVM的默認設置
堆 (heap)(News Generation 和Old Generaion 之和)的設置
?????? 初始分配的內存由-Xms指定,默認是物理內存的1/64但小于1G。
?????? 最大分配的內存由-Xmx指定,默認是物理內存的1/4但小于1G。
?????? 默認空余堆內存小于40%時,JVM就會增大堆直到-Xmx的最大限制,可以由-XX:MinHeapFreeRatio=指定。
默認空余堆內存大于70%時,JVM會減少堆直到-Xms的最小限制,可以由-XX:MaxHeapFreeRatio=指定。
服務器一般設置-Xms、-Xmx相等以避免在每次GC 后調整堆的大小,所以上面的兩個參數沒啥用。?
?????? -Xmn 設置young?generation的heap大小
????? -XX:MinHeapFreeRatio與-XX:MaxHeapFreeRatio設定空閑內存占總內 存的比例范圍,這兩個參數會影響GC的頻率和單次GC的耗時。-XX:NewRatio決定young與old generation的比例。Young generation空間越大,minor collection頻率越低,但是old generation空間小了,又可能導致major collection頻率增加。-XX:NewSize和-XX:MaxNewSize直接指定了young generation的缺省大小和最大大小。
?
非堆內存 的設置
???? 默認分配為64M
???? -XX:PermSize設置最小分配空間,-XX:MaxPermSize設置最大分配空間。一般把這兩個數值設為相同,以減少申請內存空間的時間。
?
?
內存溢出 的原 因
Old Generation溢出
這種內存溢出是最常見的情況之一,產生的原因可能是:
1) 設置的內存參數過小(ms/mx, NewSize/MaxNewSize)
??? 解決方法:
???? 1G內存環境下java jvm 的參數設置參考:
??? -server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m? -Djava.awt.headless=true
2) 程序問題
單個程序持續進行消耗內存的處理,如循環幾千次的字符串處理,對字符串處理應建議使用StringBuffer。此時不會報內存溢出錯,卻會使系統持續垃 圾收集,無法處理其它請求,相關問題程序可通過Thread Dump獲取。
單個程序所申請內存過大,有的程序會申請幾十乃至幾百兆內存,此時JVM也會因無法申請到資源而出現內存溢出,對此首 先要找到相關功能,然后交予程序員修改,要找到相關程序,必須在Apache日志中尋找。
當Java對象使用完畢后,其所引用的對象卻沒有銷毀,使得JVM認為他還是活躍的對象而不進行回收,這樣累計占用了大量內存而無法釋放。由于目前市面上還沒有對系統影響小的內存分析工具,故此時只能和程序員一起定位。
?
?
Permanent Generation
溢出
通常由于
Perm
段裝載了大量的類而導致溢出,如
spring的動態生成類。
目前的解決辦法:
1) 將
Perm
Size擴大,一般256M能夠滿足要求
2) 若別無選擇,則只能將servlet的路徑加到CLASSPATH中,但一般不建議這么處理
C Heap溢出
系統對C Heap沒有限制,故C Heap發生問題時,Java進程所占內存會持續增長,直到占用所有可用系統內存
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
