標籤:過程 roots 路徑 根搜尋演算法 pac 注意 int 調用 3.2
一:類的生命週期
類的生命週期從類被載入,串連和初始化開始!
到類的卸載結束!
01.類的生命週期中,類的2進位資料位元於方法區;
02.在堆中會有一個描述這個類的Class對象;
2.1 載入: 需要類載入器
將class位元組碼檔案內容載入到記憶體中,並將這些待用資料轉化成
方法區中運行時資料結構!在堆中產生一個Class對象;
這個Class對象就是方法區類資料的訪問入口!
2.2 連結:
01.類的驗證 在編譯期間
合法???
001.類檔案的結構檢查
002.語義檢查 比如說final修飾的變數在編譯期間發現再次賦值
003.位元組碼驗證,確保位元組碼能被jvm識別
02.類的準備
為類中所有static修飾的內容開闢空間,並且賦予初始值!!!
static int num =100;
這時候 num=0;
03.類的解析
把類中所有的符號引用轉換成直接引用!
符號引用:就是用字串的形式來表示某個變數或者是類,我們能看懂
String a="a"; Student stu=new Student();
a,stu都是符號引用!
直接引用:是根據符號引用翻譯出來的地址!
2.3 初始化
載入不是初始化!
初始化指的是執行個體化!建立出類的執行個體!
初始化的時機:
01.類的主動引用
001.new一個類的對象
002.通過反射的newInstance()
003.再初始化子類的時候必須先初始化父類
02.類的被動引用
001.通過類名訪問靜態內容
002.調用類的靜態常量也不會初始化類
003.用類作為對象數組存在時,也不會初始化類
004.子類調用父類的靜態變數不會載入子類的靜態代碼塊(不會執行類的準備階段)
三:記憶體回收機制(GC)
3.1:為什麼需要記憶體回收機制
01.只要是對象被建立,那麼就會在虛擬機器的堆中開闢空間;
02.程式運行過程中會建立N個對象,每個對象都會有自己的空間;
03.如果每個對象都永久的佔有這塊記憶體空間,顯然記憶體是不夠的!
為了保證其他的對象能夠被正確的建立!
在C語言中,記憶體回收的任務是程式猿自身負責!
可能出現的問題:
01.由於程式猿的粗心大意,導致沒有及時釋放不使用的對象,釋放錯誤!
02.程式猿一旦釋放了程式核心對象(比如說系統對象),系統崩潰!
3.2:記憶體回收機制的定義
在java程式運行過程中,JVM中有一個專門負責回收那些不再使用的對象所佔用的記憶體!
這種回收的過程,我們稱之為記憶體回收機制(GC,Garbage Collection)!
3.3:記憶體回收機制的特點
01.減輕了程式猿進行記憶體管理的負擔;
02.防止系統記憶體被非法釋放,使我們的程式更加健壯;
03.只有在對象不被任何變數引用時,才能被回收;
04.程式無法強制讓記憶體回收行程立即回收垃圾操作;
05.當記憶體回收行程將要回收不用對象的記憶體時,會先調用這個對象的finalize()
這個方法有可能使對象複活,導致記憶體回收行程取消對該對象記憶體的回收。
3.4:對象的狀態
在java虛擬機器的記憶體回收行程來看,堆中所有的對象都有3種狀態!
01.可觸及狀態
02.可複活狀態
03.不可觸及狀態
只有對象處於不可觸及狀態的時候,記憶體回收期才會真正的釋放對象所佔有的記憶體!
1.對象的生命週期開始 (new語句或者是反射中newInstance) 可觸及狀態
2.對象不在被引用,或者對象調用了finalize() 可複活狀態
3.對象調用了finalize() 不可觸及狀態
4.記憶體回收
5.對象的生命週期結束
3.5:垃圾何時被回收(觸發GC的條件)
01.對象沒有引用===》對象處於不可觸及狀態
02.程式在範圍正常執行完畢之後
03.System.exit()
04.程式以外終止
3.6:詳解GC
01.什麼時間===》觸發GC的條件
001.System.gc()可能觸發;
002.系統自身決定GC的觸發時機
根據Eden區和From Space區的記憶體大小來決定!
02.對什麼東西
java中的對象===》通過分析演算法無法找到的對象
03.做了什麼
對搜尋到的對象進行複製操作;
對搜尋不到的對象執行finalize()。
如果真正的回收一個對象,要至少需要兩次標記!
01.第一次標記:對於一個沒有其他對象引用的時候;執行finalize()
02.第二次標記:針對於篩選過的對象,進行回收。
3.7:java中記憶體配置機制
核心:分代分配,分代回收!
新生代(Young Generation)
Eden 區 :是連續的記憶體空間,所以分配記憶體極快
Survivor 區 :From To 必須有一個地區是空的=
老年代(Old Generation)
永久代(Permanet Generation)===》方法區
回收兩種資料:
01.常量池中的常量
02.無用的類資訊
什麼時候回收?
01.類所有的執行個體都被回收了
02.載入類的ClassLoader也被回收了
03.類對應的Class對象沒有被引用
注意點:
01.絕大多數建立的對象被分配在Eden區,但是大多數對象會在這個地區死亡!
02.當Eden區滿的時候,會執行Minor GC(Young GC),將死亡的對象清理掉,
剩餘存活的對象存放到survivor0區(survivor1區必然為空白)
03.以後每次Eden區滿的時候,會執行Minor GC,所有存活的對象又被放進survivor0區
04.當survivor0區滿的時候,會把存活的對象複製到survivor1區,之後清空survivor0區!
05.反覆執行之後,仍然活著的對象複製到老年代!
06.老年代的記憶體比年輕代要大,但是也有滿的時候,當老年代滿的時候執行Major GC(Full GC)
07.如果對象比較大,年輕代存放不下,就會直接把對象放進老年代!
Young GC和Full GC的區別:
01.Young GC是在新生代的Eden區滿,Survivor區滿的時候觸發
Full GC 是在老年代滿的時候觸發
02.Young GC執行的頻率高
Full GC 執行的頻率低
什麼時候觸發Full GC
01.執行System.gc(),系統建議執行Full GC,但不是必須執行
02.老年代空間不足
001.當Young GC執行後存活的對象需要進駐老年代,但是發現老年代空間不足
002.當Survivor0區,Survivor1區來回切換時,發現記憶體不足,必須放進老年代,而且老年代空間不足
03.方法區空間不足
3.8:GC涉及到的演算法
01.引用計數法 Reference Counting
給對象增加一個引用計數器,使用一次引用+1,少一個引用-1!
當引用為0的時候回收!
但是不能解決循環參考的問題!
02.根搜尋演算法 GC Roots Tracing
對象以根作為起點,向下延伸,延伸的路徑我們稱之為 引用鏈(Reference Chain)
當一個對象沒有任何引用鏈串連時,證明這個對象時停用對象(不可達),會被回收!
什麼是根?
01.方法區中常量引用的對象
02.棧中引用的對象
03.靜態屬性引用的對象
03.複製演算法 Copying
就是將原有的記憶體空間分為兩塊,每次只能使用其中一塊!
缺點就是浪費一半的記憶體空間!比標記-清除演算法要高效!
不適合存活對象較多的地區使用!
在新生代使用!
04.標記-清除演算法 Mark-Sweep
001.把所有存活的對象打個標記
002.把所有沒有標記的對象統一清除
缺點:
01.兩個過程效率都慢,因為需要想查詢
02.因為在清除過程中會產生記憶體片段,如果有大對象將無法儲存
04.標記-整理演算法 Mark-Compact
適合存活對象多的地區,所以適合在老年代使用!
JAVA 中的類