你真的知道Java中對(duì)象的銷毀嗎
在日常的開(kāi)發(fā)中、我們都知道,Java的內(nèi)存清理是通過(guò)垃圾回收器進(jìn)行的,那么其是如何將沒(méi)用的對(duì)象被被清理掉的呢?
Java 語(yǔ)言的內(nèi)存自動(dòng)回收稱為垃圾回收(Garbage Collection)機(jī)制,簡(jiǎn)稱 GC。垃圾回收機(jī)制是指 JVM 用于釋放那些不再使用的對(duì)象所占用的內(nèi)存。
Java對(duì)象在使用后需要清理。 對(duì)象清理是釋放該對(duì)象所占用的內(nèi)存。 在創(chuàng)建對(duì)象時(shí),用戶必須使用new操作符為對(duì)象分配內(nèi)存。 清除對(duì)象后,系統(tǒng)會(huì)自動(dòng)回收內(nèi)存,不需要用戶進(jìn)行額外的處理。 這也是Java語(yǔ)言的一個(gè)特性,它使程序員更容易管理內(nèi)存。
一般一個(gè)對(duì)象被當(dāng)作垃圾回收的情況主要如下兩種。
1)對(duì)象的引用超過(guò)其作用范圍。
{ Object o = new Object(); // 對(duì)象o的作用范圍,超過(guò)這個(gè)范圍對(duì)象將被視為垃圾 }
2)對(duì)象被賦值為 null
{ Object o = new Object(); o = null; // 對(duì)象被賦值為null將被視為垃圾 }
在 Java 的 Object 類中還提供了一個(gè) protected 類型的 finalize() 方法,因此任何 Java 類都可以覆蓋這個(gè)方法,在這個(gè)方法中進(jìn)行釋放對(duì)象所占有的相關(guān)資源的操作。
那么問(wèn)題又來(lái)了,finalize()是個(gè)什么鬼呀,既然會(huì)調(diào)用對(duì)象的這個(gè)方法就說(shuō)明所有的類都會(huì)有這個(gè)方法(畢竟所有的類都會(huì)被回收嘛),自然而然我們就想到了java的根類 Object.進(jìn)去看看?
protected void finalize() throws Throwable { }
最后一行還真找到了,是一個(gè)實(shí)現(xiàn)為空的方法,既然是protected就說(shuō)明具體的方法可以留給子類去實(shí)現(xiàn)之前我們說(shuō)過(guò)只有當(dāng)對(duì)象不再被任何引用指向時(shí)候,該對(duì)象才會(huì)被回收。那么真的是這樣嗎?我們舉個(gè)栗子看看
public class User { private int money; public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public void cool(){ String str=new String(); } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub if(money>0){ System.out.println("error"); }else{ System.out.println("suceess"); } super.finalize(); } }
這里我們重寫finalize()方法,在銷毀前如果一個(gè)人的前還沒(méi)花光,打印這個(gè)人是失敗的,否則這個(gè)人是成功的。下面是我們?cè)趍ain()中的代碼
public class Test { public static void main(String args[]){ User u1=new User(200); new Object(); new User(100); } }
運(yùn)行結(jié)果居然什么都沒(méi)有!運(yùn)行結(jié)束之后不光有引用指向的u1,就連沒(méi)有任何引用指向的new User(100);居然都沒(méi)有被回收。這是怎么回事呢?
我們來(lái)看看Thinking In Java中是怎樣解釋的
java中的并非總是被垃圾回收,也就是說(shuō)對(duì)象可能不被回收。一般程序只要不到瀕臨存儲(chǔ)空間用光,垃圾回收器一般都不會(huì)主動(dòng)回收內(nèi)存,如果程序結(jié)束,并且垃圾回收器一直沒(méi)有釋放你創(chuàng)建的空間,則隨著程序的退出,資源則會(huì)被歸還給操作系統(tǒng)。所以上面的我們finalize()才一直沒(méi)有被調(diào)用
如果我們想看到效果,可以通過(guò)如下方法:
public class Test { public static void main(String args[]){ User u1=new User(200); new Object(); new User(100); System.gc(); } }
System.gc();會(huì)強(qiáng)制系統(tǒng)垃圾回收器工作,運(yùn)行效果會(huì)出現(xiàn)error
說(shuō)明new User(100);創(chuàng)建的對(duì)象被回收了。
注意:調(diào)用 System.gc() 或者 Runtime.gc() 方法也不能保證回收操作一定執(zhí)行,它只是提高了 Java 垃圾回收器盡快回收垃圾的可能性。
知識(shí)補(bǔ)充:
在 Java 虛擬機(jī)的堆區(qū),每個(gè)對(duì)象都可能處于以下三種狀態(tài)之一。
1)可觸及狀態(tài):當(dāng)一個(gè)對(duì)象被創(chuàng)建后,只要程序中還有引用變量引用它,那么它就始終處于可觸及狀態(tài)。
2)可復(fù)活狀態(tài):當(dāng)程序不再有任何引用變量引用該對(duì)象時(shí),該對(duì)象就進(jìn)入可復(fù)活狀態(tài)。在這個(gè)狀態(tài)下,垃圾回收器會(huì)準(zhǔn)備釋放它所占用的內(nèi)存,在釋放之前,會(huì)調(diào)用它及其他處于可復(fù)活狀態(tài)的對(duì)象的 finalize() 方法,這些 finalize() 方法有可能使該對(duì)象重新轉(zhuǎn)到可觸及狀態(tài)。
3)不可觸及狀態(tài):當(dāng) Java 虛擬機(jī)執(zhí)行完所有可復(fù)活對(duì)象的 finalize() 方法后,如果這些方法都沒(méi)有使該對(duì)象轉(zhuǎn)到可觸及狀態(tài),垃圾回收器才會(huì)真正回收它占用的內(nèi)存。
總結(jié)
到此這篇關(guān)于Java中對(duì)象銷毀的文章就介紹到這了,更多相關(guān)Java中對(duì)象的銷毀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java分頁(yè)簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了Java分頁(yè)簡(jiǎn)介的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素
今天給大家?guī)?lái)的文章是關(guān)于Java的相關(guān)知識(shí),文章圍繞著為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06在IntelliJ?IDEA中配置SSH服務(wù)器開(kāi)發(fā)環(huán)境并實(shí)現(xiàn)固定地址遠(yuǎn)程連接的操作方法
本文主要介紹如何在IDEA中設(shè)置遠(yuǎn)程連接服務(wù)器開(kāi)發(fā)環(huán)境,并結(jié)合Cpolar內(nèi)網(wǎng)穿透工具實(shí)現(xiàn)無(wú)公網(wǎng)遠(yuǎn)程連接,然后實(shí)現(xiàn)遠(yuǎn)程Linux環(huán)境進(jìn)行開(kāi)發(fā),本例使用的是IDEA2023.2.5版本,感興趣的朋友跟隨小編一起看看吧2024-01-01Spring 事件監(jiān)聽(tīng)機(jī)制實(shí)現(xiàn)跨模塊調(diào)用的思路詳解
之前一個(gè)項(xiàng)目,有兩個(gè)模塊,A 模塊需要依賴 B 模塊,但現(xiàn)在 B 模塊有地方需要調(diào)用 A 模塊的方法,如果直接依賴,又會(huì)產(chǎn)生循環(huán)依賴問(wèn)題,最終選擇使用 spring 的事件監(jiān)聽(tīng)來(lái)解決該問(wèn)題,下面給大家介紹Spring 事件監(jiān)聽(tīng)機(jī)制實(shí)現(xiàn)跨模塊調(diào)用的思路,感興趣的朋友一起看看吧2024-05-05IDEA配置maven環(huán)境的詳細(xì)教程(Unable to import maven project報(bào)錯(cuò)問(wèn)題的解決)
這篇文章主要介紹了IDEA配置maven環(huán)境的詳細(xì)教程(Unable to import maven project問(wèn)題的解決),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06SpringBoot開(kāi)發(fā)技巧啟動(dòng)時(shí)配置校驗(yàn)實(shí)現(xiàn)示例
這篇文章主要為大家介紹了SpringBoot開(kāi)發(fā)在啟動(dòng)時(shí)自動(dòng)配置校驗(yàn)的實(shí)現(xiàn)示例及原理解析,有需要的朋友可以借鑒參考下希望能夠有所幫助2021-10-10spring,mybatis事務(wù)管理配置與@Transactional注解使用詳解
這篇文章主要介紹了spring,mybatis事務(wù)管理配置與@Transactional注解使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07