1绑改、java四種引用類型
2迹卢、JVM內(nèi)存模型
http://www.reibang.com/p/1579aafac60b
《深入理解JVM虛擬機》中JVM內(nèi)存模型可以分為五個區(qū)域兩種類型肪笋,兩大塊,一個是線程私有靖榕,一個是線程共享數(shù)據(jù)區(qū)。
5個數(shù)據(jù)區(qū)包括:方法區(qū)、堆區(qū)锤岸、虛擬機棧、本地方法棧板乙、程序計數(shù)器是偷。
所有線程共享的數(shù)據(jù)區(qū):
- 方法區(qū): 存儲已被虛擬機加載的類信息、常量募逞、靜態(tài)變量蛋铆、即時編譯后代碼等數(shù)據(jù)。常量池位于方法區(qū)放接,并使用永久代來實現(xiàn)方法區(qū)
- 堆區(qū): 我們常說用于存放對象的區(qū)域
線程私有(隔離)數(shù)據(jù)區(qū):
- 虛擬機棧: 方法執(zhí)行時創(chuàng)建一個棧幀刺啦,用于存儲局部變量、操作數(shù)棧纠脾、動態(tài)鏈接玛瘸、方法出口等信息蜕青。每個方法一個棧幀,互不干擾
- 本地方法棧: 用于存放執(zhí)行native方法的運行數(shù)據(jù)
- 程序計數(shù)器: 當前線程所執(zhí)行的字節(jié)碼的指示器糊渊,通過改變計數(shù)器來選取下一條需要執(zhí)行的字節(jié)碼指令
上面基本都能理解市咆,但是需要著重理解下虛擬機棧和本地方法棧,虛擬機棧是java方法的內(nèi)存區(qū)域再来,調(diào)用一個方法就會創(chuàng)建一個棧幀蒙兰,用來存儲局部變量,用于存儲局部變量表芒篷、方法出口等信息搜变,棧是動態(tài)創(chuàng)建和消亡的,方法調(diào)用結(jié)束针炉,則棧幀就消失挠他。而,本地方法棧是為java的native方法服務篡帕。
native方法是什么殖侵?
3、垃圾回收
https://blog.csdn.net/justloveyou_/article/details/71216049
- 那些內(nèi)存需要回收镰烧?(對象是否可以被回收的兩種經(jīng)典算法: 引用計數(shù)法 和 可達性分析算法)
- 什么時候回收拢军? (堆的新生代、老年代怔鳖、永久代的垃圾回收時機茉唉,MinorGC 和 FullGC)
- 如何回收?(三種經(jīng)典垃圾回收算法(標記清除算法结执、復制算法度陆、標記整理算法)及分代收集算法 和 七種垃圾收集器)
對象存活判斷
1)引用計數(shù)
簡單咯,略
2)可達性分析:
通過一些列稱為“GC roots”的對象作為起始點献幔,開始向下搜索懂傀,走過的路徑稱為引用鏈,蜡感,當一個對象沒有路徑到達任意的GC roots時蹬蚁,圖論中說法就是不可達,則表示對象不可用铸敏,可以回收缚忧。
垃圾收集
1)標記清除算法
從根節(jié)點開始遍歷,先對遍歷到的節(jié)點進行標記杈笔,然后掃描整個空間中未被標記的部分闪水,進行回收。
標記-清除算法的主要不足有兩個:
效率問題:標記和清除兩個過程的效率都不高;
空間問題:標記-清除算法不需要進行對象的移動,并且僅對不存活的對象進行處理球榆,因此標記清除之后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片朽肥,空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作.
2) 復制算法
復制算法將可用內(nèi)存按容量劃分為大小相等的兩塊持钉,每次只使用其中的一塊衡招。當這一塊的內(nèi)存用完了,就將還存活著的對象復制到另外一塊上面每强,然后再把已使用過的內(nèi)存空間一次清理掉始腾。這種算法適用于對象存活率低的場景,比如新生代空执。這樣使得每次都是對整個半?yún)^(qū)進行內(nèi)存回收浪箭,內(nèi)存分配時也就不用考慮內(nèi)存碎片等復雜情況,只要移動堆頂指針辨绊,按順序分配內(nèi)存即可奶栖,實現(xiàn)簡單,運行高效门坷。當然缺點就是將內(nèi)存減少到原來的一半宣鄙。
當然現(xiàn)在的內(nèi)存空間并不需要1:1去劃分,因為大多數(shù)對象都是“朝生夕死”默蚌,生存期短冻晤,根據(jù)將新生代內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間 (如下圖所示),每次使用Eden和其中一塊Survivor敏簿。當回收時明也,將Eden和Survivor中還存活著的對象一次地復制到另外一塊Survivor空間上,最后清理掉Eden和剛才用過的Survivor空間惯裕。HotSpot虛擬機默認Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用內(nèi)存空間為整個新生代容量的90% ( 80%+10% )绣硝,只有10% 的內(nèi)存會被“浪費”蜻势。
新生代中使用復制算法較低,因為存活對象比較少鹉胖,不需要頻繁復制握玛。
3) 標記整理算法
復制收集算法在對象存活率較高時就要進行較多的復制操作,效率將會變低甫菠。更關鍵的是挠铲,如果不想浪費50%的空間,就需要有額外的空間進行分配擔保寂诱,以應對被使用的內(nèi)存中所有對象都100%存活的極端情況拂苹,所以在老年代一般不能直接選用這種算法。
標記整理算法的標記過程類似標記清除算法痰洒,但后續(xù)步驟不是直接對可回收對象進行清理瓢棒,而是讓所有存活的對象都向一端移動浴韭,然后直接清理掉端邊界以外的內(nèi)存,類似于磁盤整理的過程脯宿,該垃圾回收算法適用于對象存活率高的場景(老年代)
分代收集算法
對于一個大型的系統(tǒng)念颈,當創(chuàng)建的對象和方法變量比較多時,堆內(nèi)存中的對象也會比較多连霉,如果逐一分析對象是否該回收榴芳,那么勢必造成效率低下。分代收集算法是基于這樣一個事實:不同的對象的生命周期(存活情況)是不一樣的跺撼,而不同生命周期的對象位于堆中不同的區(qū)域翠语,因此對堆內(nèi)存不同區(qū)域采用不同的策略進行回收可以提高 JVM 的執(zhí)行效率。當代商用虛擬機使用的都是分代收集算法:新生代對象存活率低财边,就采用復制算法肌括;老年代存活率高,就用標記清除算法或者標記整理算法酣难。Java堆內(nèi)存一般可以分為新生代谍夭、老年代和永久代。
4憨募、類加載機制
先放一放