java gc回收区域_java内存区域以及GC回收
參考資料:
http://www.cnblogs.com/zhguang/p/3257367.html
概要:
Java GC機制主要完成3件事:確定哪些內存需要回收,確定什么時候需要執行GC,如何執行GC。
從4個方面學習Java GC機制,
1,內存是如何分配的;
2,如何保證內存不被錯誤回收(即:哪些內存需要回收);
3,在什么情況下執行GC以及執行GC的方式;
4,如何監控和優化GC機制。
程序計數器也是所有JVM內存區域中唯一一個沒有定義OutOfMemoryError的區域。
一般來說,一個Java的引用訪問涉及到3個內存區域:JVM棧,堆,方法區。
通過直接指針訪問的方式中,reference中存儲的就是對象在堆中的實際地址,在堆中存儲的對象信息中包含了在方法區中的相應類型數據。這種方法最大的優勢是速度快,在HotSpot虛擬機中用的就是這種方式。
GC回收:
Java內存分配和回收的機制概括的說,就是:分代分配,分代回收。對象將根據存活的時間被分為:年輕代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法區)
在年輕代,進行的垃圾回收方法是著名的“停止-復制”清理法;
年輕代(Young Generation):對象被創建時,內存的分配首先發生在年輕代(大對象可以直接被創建在年老代),大部分的對象在創建后很快就不再使用,因此很快變得不可達,于是被年輕代的GC機制清理掉(IBM的研究表明,98%的對象都是很快消亡的),這個GC機制被稱為Minor GC或叫Young GC。注意,Minor GC并不代表年輕代內存不足,它事實上只表示在Eden區上的GC。
年輕代上的內存分配是這樣的,年輕代可以分為3個區域:Eden區(伊甸園,亞當和夏娃偷吃禁果生娃娃的地方,用來表示內存首次分配的區域,再貼切不過)和兩個存活區(Survivor 0 、Survivor 1)。內存分配過程為(來源于《成為JavaGC專家part I》,http://www.importnew.com/1993.html):
絕大多數剛創建的對象會被分配在Eden區,其中的大多數對象很快就會消亡。Eden區是連續的內存空間,因此在其上分配內存極快;
當Eden區滿的時候,執行Minor GC,將消亡的對象清理掉,并將剩余的對象復制到一個存活區Survivor0(此時,Survivor1是空白的,兩個Survivor總有一個是空白的);
此后,每次Eden區滿了,就執行一次Minor GC,并將剩余的對象都添加到Survivor0;
當Survivor0也滿的時候,將其中仍然活著的對象直接復制到Survivor1,以后Eden區執行Minor GC后,就將剩余的對象添加Survivor1(此時,Survivor0是空白的)。
當兩個存活區切換了幾次(HotSpot虛擬機默認15次,用-XX:MaxTenuringThreshold控制,大于該值進入老年代,但這只是個最大值,并不代表一定是這個值)之后,仍然存活的對象(其實只有一小部分,比如,我們自己定義的對象),將被復制到老年代。
從上面的過程可以看出,Eden區是連續的空間,且Survivor總有一個為空。經過一次GC和復制,一個Survivor中保存著當前還活著的對象,而Eden區和另一個Survivor區的內容都不再需要了,可以直接清空,到下一次GC時,兩個Survivor的角色再互換。因此,這種方式分配內存和清理內存的效率都極高,這種垃圾回收的方式就是著名的“停止-復制(Stop-and-copy)”清理法(將Eden區和一個Survivor中仍然存活的對象拷貝到另一個Survivor中),這不代表著停止復制清理法很高效,其實,它也只在這種情況下高效,如果在老年代采用停止復制,則挺悲劇的。
年老代(Old Generation):對象如果在年輕代存活了足夠長的時間而沒有被清理掉(即在幾次Young GC后存活了下來),則會被復制到年老代,年老代的空間一般比年輕代大,能存放更多的對象,在年老代上發生的GC次數也比年輕代少。當年老代內存不足時,將執行Major GC,也叫 Full GC。
可以使用-XX:+UseAdaptiveSizePolicy開關來控制是否采用動態控制策略,如果動態控制,則動態調整Java堆中各個區域的大小以及進入老年代的年齡。
如果對象比較大(比如長字符串或大數組),Young空間不足,則大對象會直接分配到老年代上(大對象可能觸發提前GC,應少用,更應避免使用短命的大對象)。用-XX:PretenureSizeThreshold來控制直接升入老年代的對象大小,大于這個值的對象會直接分配在老年代上。
可能存在年老代對象引用新生代對象的情況,如果需要執行Young GC,則可能需要查詢整個老年代以確定是否可以清理回收,這顯然是低效的。解決的方法是,年老代中維護一個512 byte的塊——”card table“,所有老年代對象引用新生代對象的記錄都記錄在這里。Young GC時,只要查這里即可,不用再去查全部老年代,因此性能大大提高。
總結
以上是生活随笔為你收集整理的java gc回收区域_java内存区域以及GC回收的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 李想自曝:电吸门前装成本仅500 后期加
- 下一篇: java 如何实现计数_如何高效的实现一