解讀JVM對象生命周期之創建階段
本文向大家介紹一下JVM對象生命周期的概念,在JVM運行空間中,對象的整個生命周期大致可以分為7個階段:創建階段(Creation)、應用階段(Using)、不可視階段(Invisible)、不可到達階段(Unreachable)、可收集階段(Collected)、終結階段(Finalized)與釋放階段(Free),這里簡單說一下創建階段。
詳細解讀JVM對象生命周期
在JVM運行空間中,整個JVM對象生命周期大致可以分為7個階段:創建階段(Creation)、應用階段(Using)、不可視階段(Invisible)、不可到達階段(Unreachable)、可收集階段(Collected)、終結階段(Finalized)與釋放階段(Free)。上面的這7個階段,構成了JVM中對象的完整的生命周期。下面分別介紹對象在處于這7個階段時的不同情形。
創建階段
在對象創建階段,系統要通過下面的步驟,完成對象的創建過程:
(1)為對象分配存儲空間。
(2)開始構造對象。
(3)遞歸調用其超類的構造方法。
(4)進行對象實例初始化與變量初始化。
(5)執行構造方法體。
上面的5個步驟中的第3步就是指遞歸地調用該類所擴展的所有父類的構造方法,一個Java類(除Object類外)至少有一個父類(Object),這個規則既是強制的,也是隱式的。你可能已經注意到在創建一個Java類的時候,并沒有顯式地聲明擴展(extends)一個Object父類。實際上,在Java程序設計中,任何一個Java類都直接或間接的是Object類的子類。例如下面的代碼:
- publicclassA{
- …
- }
- 這個聲明等同于下面的聲明:
- publicclassAextendsjava.lang.Object{
- …
- }
上面講解了對象處于創建階段時,系統所做的一些處理工作,其中有些過程與應用的性能密切相關,因此在創建對象時,我們應該遵循一些基本的規則,以提高應用的性能。
下面是JVM對象生命周期在創建對象時的幾個關鍵應用規則:
(1)避免在循環體中創建對象,即使該對象占用內存空間不大。
(2)盡量及時使對象符合垃圾回收標準。
(3)不要采用過深的繼承層次。
(4)訪問本地變量優于訪問類中的變量。
關于規則(1)避免在循環體中創建對象,即使該對象占用內存空間不大,需要提示一下,這種情況在我們的實際應用中經常遇到,而且我們很容易犯類似的錯誤,例如下面的代碼:
- ……
- for(inti=0;i<10000;++i){
- Objectobj=newObject();
- System.out.println("obj="+obj);
- }
- ……
上面代碼的書寫方式相信對你來說不會陌生,也許在以前的應用開發中你也這樣做過,尤其是在枚舉一個Vector對象中的對象元素的操作中經常會這樣書寫,但這卻違反了上述規則(1),因為這樣會浪費較大的內存空間,正確的方法如下所示:
- ……
- Objectobj=null;
- for(inti=0;i<10000;++i){
- obj=newObject();
- System.out.println("obj="+obj);
- }
- ……
采用上面的第二種編寫方式,僅在內存中保存一份對該對象的引用,而不像上面的***種編寫方式中代碼會在內存中產生大量的對象應用,浪費大量的內存空間,而且增大了系統做垃圾回收的負荷。因此在循環體中聲明創建對象的編寫方式應該盡量避免。
另外,不要對一個對象進行多次初始化,這同樣會帶來較大的內存開銷,降低系統性能,如:
- publicclassA{
- privateHashtabletable=newHashtable();
- publicA(){
- //將Hashtable對象table初始化了兩次
- table=newHashtable();
- }
- }
正確的方式為:
- publicclassB{
- privateHashtabletable=newHashtable();
- publicB(){
- }
- }
不要小看這個差別,它卻使應用軟件的性能相差甚遠,如圖2-5所示。
看來在程序設計中也應該遵從“勿以惡小而為之”的古訓,否則我們開發出來的應用也是低效的應用,有時應用軟件中的一個極小的失誤,就會大幅度地降低整個系統的性能。因此,我們在日常的應用開發中,應該認真對待每一行代碼,采用***化的編寫方式,不要忽視細節,不要忽視潛在的問題。本節關于JVM對象生命周期的***個階段就介紹到這里,請看下節有關其他階段的介紹。
【編輯推薦】