java对象生命周期_Java对象生命周期和类生命周期
原標題:Java對象生命周期和類生命周期
作者:彭空空
鏈接:https://www.jianshu.com/p/25ea857ba78b
導讀
對象的生命周期
類的加載機制
類的生命周期
類加載器
對象的生命周期
對象的整個生命周期大致可以分為7個階段:
創建階段(Creation)
應用階段(In Use)
不可視階段(Invisible)
不可達階段(Unreachable)
可收集階段(Collected)
終結階段(Finalized)
對象空間重分配階段(De-allocated)
image 創建階段(Creation)
一個Java類至少有一個父類Object(除了Object類本身),這個規則既是強制的,也是隱式的。你可能已經注意到在創建一個Java類的時候,并沒有顯式地聲明擴展(extends)一個Object父類。
1//TempA的聲明等同于TempB
2publicclassTempA{ }
3publicclassTempBextendsjava.lang.Object{ }
在創建階段系統通過以下的幾個步驟來完成對象的創建過程:
為對象分配存儲空間
開始構造對象
從超類到子類對static成員進行初始化
超類成員變量按順序初始化,遞歸調用超類的構造方法
子類成員變量按順序初始化,子類構造方法調用
一旦對象被創建,并被分派給某些變量賦值,這個對象的狀態就切換到了應用階段
應用階段(Using)
對象至少被一個強引用持有著。
不可視階段(Invisible)
當一個對象處于不可見階段時,說明程序本身不再持有該對象的任何強引用,但是這些引用可能還存在著,**一般具體是指程序的執行已經超過該對象的作用域了。
1boolean bool= false;
2if( bool){
3intcount = 0;
4count++;
5}
6System. out.println(count);
本地變量count在System.out.println(count)時已經超出了其作用域,則在此時稱之為count處于不可視階段。當然這樣的情況編譯器在編譯的過程中會直接報錯了。
不可達階段(Unreachable)
對象處于不可達階段是指該對象不再被任何強引用所持有,該對象仍可能被JVM等系統下的某些已裝載的靜態變量或線程或JNI等強引用持有著,這些特殊的強引用被稱為”GC root”。存在著這些GC root會導致對象的內存泄露情況,無法被回收。
可收集階段(Collected)
當垃圾回收器發現該對象已經處于“不可達階段”而且垃圾回收器已經對該對象的內存空間又一次分配做好準備時,則對象進入了“收集階段”。假設該對象已經重寫了finalize方法,則會去運行該方法的終端操作。
這里要特別說明一下:不要重載finazlie方法!原因有兩點:
會影響JVM的對象分配與回收速度 在分配該對象時,JVM須要在垃圾回收器上注冊該對象,以便在回收時可以運行該重載方法;在該方法的運行時須要消耗CPU時間且在運行完該方法后才會又一次運行回收操作,即至少須要垃圾回收器對該對象運行兩次GC。
可能造成該對象的再次“復活” 在finalize方法中,假設有其他的強引用再次持有該對象,則會導致對象的狀態由“收集階段”又又一次變為“應用階段”。這個已經破壞了Java對象的生命周期進程,且“復活”的對象不利用興許的代碼管理。
終結階段(Finalized)
當對象運行完finalize方法后仍然處于不可達狀態時,則該對象進入終結階段。在該階段是等待垃圾回收器對該對象空間進行回收。
對象空間重分配階段(De-allocated)
對象空間又一次分配階段,垃圾回收器對該對象的所占用的內存空間進行回收或者再分配了,則該對象徹底消失了,稱之為“對象空間又一次分配階段”。
類的加載機制
類的加載指的是將類的.class文件中的二進制數據讀入到內存中,將其放在運行時數據區的方法區內,然后在堆區創建一個java.lang.Class對象,用來封裝類在方法區內的數據結構。類的加載的最終產品是位于堆區中的Class對象,Class對象封裝了類在方法區內的數據結構,并且向Java程序員提供了訪問方法區內的數據結構的接口。
類加載器并不需要等到某個類被“首次主動使用”時再加載它,JVM規范允許類加載器在預料某個類將要被使用時就預先加載它,如果在預先加載的過程中遇到了.class文件缺失或存在錯誤,類加載器必須在程序首次主動使用該類時才報告錯誤(LinkageError錯誤)如果這個類一直沒有被程序主動使用,那么類加載器就不會報告錯誤
加載.class文件的方式
從本地系統中直接加載
通過網絡下載.class文件
從zip,jar等歸檔文件中加載.class文件
從專有數據庫中提取.class文件
將Java源文件動態編譯為.class文件
類的生命周期
image
Java虛擬機為Java程序提供運行時環境,其中一項重要的任務就是管理類和對象的生命周期。類的生命周期從類被加載、連接和初始化開始,到類被卸載結束。當類處于生命周期中時,它的二級制數據位于方法區內,在堆區中還會有一個相應的描述這個類的Class對象(當Java程序使用任何一個類時,系統都會為之創建一個java.lang.Class對象)。只有當類處于生命周期中時,Java程序才能使用它,比如調用類的靜態成員或者創建類的實例。
當Java程序需要使用某個類時,Java虛擬機會確保這個類已經被加載、連接和初始化。其中連接過程又包括驗證、準備和解析這三個子步驟。這些步驟必須嚴格按照以下順序執行。
加載:查找并加載類的二進制數據
查找并加載類的二進制數據加載時類加載過程的第一個階段,在加載階段,虛擬機需要完成以下三件事情:
通過一個類的全限定名來獲取其定義的二進制字節流。
將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
在Java堆中生成一個代表這個類的java.lang.Class對象,作為對方法區中這些數據的訪問入口。
相對于類加載的其他階段而言,加載階段(準確地說,是加載階段獲取類的二進制字節流的動作)是可控性最強的階段,因為開發人員既可以使用系統提供的類加載器來完成加載,也可以自定義自己的類加載器來完成加載。
加載階段完成后,虛擬機外部的二進制字節流就按照虛擬機所需的格式存儲在方法區之中,而且在Java堆中也創建一個java.lang.Class類的對象,這樣便可以通過該對象訪問方法區中的這些數據。
連接:包括驗證、準備和解析類的二進制數據
驗證:確保被加載類的正確性
當類被加載后,就進入驗證階段。連接就是把已經讀入到內存中的類的二進制數據合并到JVM運行時環境中去。連接的第一步是類的驗證,其目的是保證被加載的類由正確的內部結構,并且與其他類協調一致。如果JVM檢查到錯誤,那么就會拋出相應的Error對象。
準備:為類的靜態變量分配內存,并將其初始化為默認值
解析:把類中的符號引用轉換成直接引用
初始化
如果一個類被直接引用,就會觸發類的初始化。在java中,直接引用的情況有:
通過new關鍵字實例化對象、讀取或設置類的靜態變量、調用類的靜態方法。
通過反射方式執行以上三種行為。
初始化子類的時候,會觸發父類的初始化。
作為程序入口直接運行時(也就是直接調用main方法)。
除了以上四種情況,其他使用類的方式叫做被動引用,而被動引用不會觸發類的初始化。
卸載
在類使用完之后,如果滿足下面的情況,類就會被卸載:
該類所有的實例都已經被回收,也就是java堆中不存在該類的任何實例。
加載該類的ClassLoader已經被回收
該類對應的java.lang.Class對象沒有任何地方被引用,無法在任何地方通過反射- 訪問該類的方法
jvm(java虛擬機)中的幾個比較重要的內存區域
方法區:在java的虛擬機中有一塊專門用來存放已經加載的類信息、常量、靜態變量以及方法代碼的內存區域,叫做方法區。
常量池:常量池是方法區的一部分,主要用來存放常量和類中的符號引用等信息。
堆區:用于存放類的對象實例。
棧區:也叫java虛擬機棧,是由一個一個的棧幀組成的后進先出的棧式結構,棧楨中存放方法運行時產生的局部變量、方法出口等信息。當調用一個方法時,虛擬機棧中就會創建一個棧幀存放這些數據,當方法調用完成時,棧幀消失,如果方法中調用了其他方法,則繼續在棧頂創建新的棧楨。
類加載器(Calssloader)
image
未完待續。。。
文獻
https://www.cnblogs.com/9513-/p/8456877.html
https://www.cnblogs.com/wangxilei/p/9617637.html
https://www.cnblogs.com/damon9094/p/8881185.html
https://blog.csdn.net/m0_38075425/article/details/81627349返回搜狐,查看更多
責任編輯:
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的java对象生命周期_Java对象生命周期和类生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 64位 默认分配内存大小_查看
- 下一篇: java 注册回调_java 实现回调代