java的finalize()方法與C++的析構函數


---《java編程思想》 讀書筆記
--- 2017/3/15

讀《java編程思想》讀到初始化與清理一章,文中提及java的finalize()方法,聯想到了C++的析構函數。finalize()方法與析構函數存在天然差別,這種差別源於語言本身機制的不同。

在C++中,對象是可以在棧上分配的,也可以在堆上分配。在棧上分配的對象,也就是函數的局部變量,當超出塊的"}"時,生命期便結束了。在堆上分配的對象,使用delete的時候,對象的生命期也就結束了。因此在C++中,對象的內存在哪個時刻被回收,是可以確定的(假設程序沒有缺陷)。java秉承一切皆為對象的思想,對象僅能通過new來創建,因此java的對象是在堆上分配的內存。這些堆上的對象,如果沒有作用了(無引用指向它),將等待垃圾回收器來回收其占用的內存。而垃圾回收期何時運行,無法提前預知,甚至有的時候直到程序退出都沒有進行垃圾回收,程序所占內存直接由操作系統來回收。所以在java中,對象的內存在哪個時刻回收,取決於垃圾回收器何時運行。因此,C++與java中,對無用對象的回收時間是不同的。

一旦C++的對象要被回收了,在回收該對象之前對象的析構函數將被調用,然后釋放對象占用的內存;而java中

一旦垃圾回收器准備好釋放對象占用的存儲空間,將首先調用其finalize()方法, 並且在下一次垃圾回收動作發生時,才會真正的回收對象占用的內存(《java 編程思想》)

可見在java中,調用GC不等於真正地回收內存資源,而且在垃圾回收中對象存在狀態的變化。

C++的析構函數用來做一些必要的工作,例如釋放掉指針成員所指向的對象所占的內存,因為C++沒有java的垃圾回收器,所有new出來的對象,都要顯式地delete掉,避免內存泄漏。《Effective C++》中提及,基類需要將析構函數聲明為virtual函數,這是為了可以通過子類對象指針正確地釋放掉基類的資源。總的來說,在C++中,析構函數和資源的釋放息息相關,能不能正確處理析構函數,關乎能否正確回收對象內存資源。 在java中,所有的對象,包括對象中包含的其他對象,它們所占的內存的回收都依靠垃圾回收器,因此不需要一個函數如C++析構函數那樣來做必要的垃圾回收工作。當然存在本地方法時需要finalize()方法來清理本地對象。在《java編程思想》中提及,finalize()方法的一個作用是用來回收“本地方法”中的本地對象——C/C++代碼所分配的內存,由於這部分的內存只能由delete/free來釋放,因此可以放在finalize()方法中來做。在實際生產環境中,我較少(或說基本沒有)看到java類實現了finalize()方法。可以說java最大程度地弱化了內存管理對應用程序員的束縛,而c++則對此要求嚴格多了。

另外,看到了兩篇介紹java對象回收流程的文章:https://my.oschina.net/u/1412027/blog/181710 http://blog.csdn.net/rsljdkt/article/details/12242007
這些內容應該是在JVM的書籍中有涉及,這又是值得研究的一個點了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM