java中对象的生存期_Java中对象的生存周期
文章目錄
JAVA對象的生存周期
1.創(chuàng)建階段(Created)
為對象分配內(nèi)存需要考慮的問題
2.應用階段(In Use)
3.不可見階段(Invisible)
4.不可達階段(Unreachable)
5.收集階段(Collected)
6.終結階段
7.對象空間重新分配階段
JAVA對象的生存周期
在Java中,對象的生命周期包括以下幾個階段:
創(chuàng)建階段(Created)
應用階段(In Use)
不可見階段(Invisible)
不可達階段(Unreachable)
收集階段(Collected)
終結階段(Finalized)
對象空間重分配階段(De-allocated)
1.創(chuàng)建階段(Created)
在創(chuàng)建階段系統(tǒng)通過下面的幾個步驟來完成對象的創(chuàng)建過程
虛擬機遇到new指令,首先去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用。
檢查符號引用的類是否引進被加載,如果沒有被加載,則執(zhí)行相應的類加載過程。
為對象分配內(nèi)存(為對象分配的內(nèi)存大小在類加載時已經(jīng)確定)(為對象分配內(nèi)存還有一點知識點我在后面贅述)
開始構造對象
從超類到子類對static成員進行初始化
超類成員變量按順序初始化,遞歸調(diào)用超類的構造方法
子類成員變量按順序初始化,子類構造方法調(diào)用
一旦對象被創(chuàng)建,并被分派給某些變量賦值,這個對象的狀態(tài)就切換到了應用階段
Java對象的創(chuàng)建這里涉及到知識點儲備需要知道,下面這些基本的知識,下面點擊鏈接可以自行查閱。
JVM內(nèi)存區(qū)域劃分
JVM類生命周期概述:加載時機與加載過程
為對象分配內(nèi)存需要考慮的問題
問題一:堆內(nèi)存的分配方式
為對象分配內(nèi)存時,對象需要的內(nèi)存大小在類加載時就已經(jīng)確定,這里為對象分配空間的任務相當于把一塊確定大小的內(nèi)存從堆中劃分出來。而堆內(nèi)存的分配方式是我們這里要說的第一個問題:
分配方式一:指針碰撞
假設JVM中堆的內(nèi)存是絕對規(guī)整的,空閑的內(nèi)存在一遍,已經(jīng)被使用的內(nèi)存在一遍,中間由一個指針進行分割。那么對象的內(nèi)存分配就由將指針移動即可。
分配方式二:空閑列表法
如果JVM中堆的內(nèi)存不是規(guī)整的,空閑的內(nèi)存和被使用的內(nèi)存相互交錯。這時虛擬機需要維護一個列表,記錄哪塊內(nèi)存時空閑的,當對象需要被分配內(nèi)存時,找到一塊足夠大的內(nèi)存分配。
**考慮分配方式取決于JVM堆內(nèi)存是否規(guī)整,而JVM內(nèi)存是否規(guī)整取決于JVM使用的垃圾回收器是否帶有垃圾整理功能。**例如:在使用Serial、ParNew 等帶Compact過程的收集器時,系統(tǒng)采用的分配算法是指針碰撞;而使用CMS這種基于Mark-Sweep算法的收集器時,通常采用空閑列表。
問題二:考慮對象是否被頻繁創(chuàng)建,線程安全問題
即使是修改一個指正,但是在并發(fā)的情況下也不是安全的。可能存在對象A正在分配的,可能出現(xiàn)正在給對象A分配內(nèi)存,指針還沒來得及修改,對象B又同時使用了原來的指針來分配內(nèi)存的情況。解決這個問題有兩種方案:
第一種:是對分配內(nèi)存空間的動作進行同步處理,實際上虛擬機采用CAS配上失敗重試的方式保證更新操作的原子性:
第二種:是把內(nèi)存分配的動作按照線程劃分在不同的空間之中進行,:即每個線程在Java堆中預先分配小塊內(nèi)存,稱為本地線程分配緩沖(Thread Local Allocation Buffer, TLAB)。 哪個線程要分配內(nèi)存,就在哪個線程的TLAB上分配,只有TLAB用完并分配新的FLAB時,才需要同步鎖定。虛擬機是否使用TLAB,可以通過-XX:+/-UseTLAB參數(shù)來設定。
內(nèi)存分配完成后,虛擬機需要將分配到的內(nèi)存空間都初始化為零值(不包括對象頭), 如果使用TLAB,這一工作過程也可以提前至TLAB分配時進行。這一步操作保證了對象的實例字段在Java代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據(jù)類型所對
應的零值。虛擬機是否使用TLAB,可以通過-XX:+/-UseTLAB參數(shù)來設定。
2.應用階段(In Use)
對象至少被一個強引用持有著。
想要了解引用的朋友可以看博文
Java中的四種引用
3.不可見階段(Invisible)
當一個對象處于不可見階段時,說明程序本身不再持有該對象的任何強引用,雖然該這些引用仍然是存在著的。
簡單說就是程序的執(zhí)行已經(jīng)超出了該對象的作用域了。
舉例如下圖:本地變量count在25行時已經(jīng)超出了其作用域,則在此時稱之為count處于不可視階段。當然這種情況編譯器在編譯的過程中會直接報錯了。
4.不可達階段(Unreachable)
對象處于不可達階段是指該對象不再被任何強引用所持有。
與“不可見階段”相比,“不可見階段”是指程序不再持有該對象的任何強引用。對象如果在之前的任何狀態(tài)被JVM等系統(tǒng)下的某些已裝載的靜態(tài)變量或線程或JNI等強引用持有著,這些特殊的強引用被稱為”GC root”。存在著這些GC root會導致對象的內(nèi)存泄露情況,無法被回收,則對方也無法到達“不可達階段”。
5.收集階段(Collected)
當垃圾回收器發(fā)現(xiàn)該對象已經(jīng)處于“不可達階段”并且垃圾回收器已經(jīng)對該對象的內(nèi)存空間重新分配做好準備時,則對象進入了“收集階段”。如果該對象已經(jīng)重寫了finalize()方法,則會去執(zhí)行該方法的終端操作。
這里要特別說明一下:不要重載finazlie()方法!原因有兩點:
l 會影響JVM的對象分配與回收速度
在分配該對象時,JVM需要在垃圾回收器上注冊該對象,以便在回收時能夠執(zhí)行該重載方法;在該方法的執(zhí)行時需要消耗CPU時間且在執(zhí)行完該方法后才會重新執(zhí)行回收操作,即至少需要垃圾回收器對該對象執(zhí)行兩次GC。
l 可能造成該對象的再次“復活”
在finalize()方法中,如果有其它的強引用再次持有該對象,則會導致對象的狀態(tài)由“收集階段”又重新變?yōu)椤皯秒A段”。這個已經(jīng)破壞了Java對象的生命周期進程,且“復活”的對象不利用后續(xù)的代碼管理。
想要了解JVM垃圾回收算法可以點擊鏈接
JVM垃圾回收算法
6.終結階段
當對象執(zhí)行完finalize()方法后仍然處于不可達狀態(tài)時,則該對象進入終結階段。在該階段是等待垃圾回收器對該對象空間進行回收。
7.對象空間重新分配階段
垃圾回收器對該對象的所占用的內(nèi)存空間進行回收或者再分配了,則該對象徹底消失了,稱之為“對象空間重新分配階段”。
總結
以上是生活随笔為你收集整理的java中对象的生存期_Java中对象的生存周期的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百一测评java基础答案_百一测评——《
- 下一篇: java美元兑换,(Java实现) 美元