JAVA
JAVAJVM为该对象分配内存、调用构造函数并开始跟踪你使用的对象。当你停止使用一个对象(就是说,当没有对该对象有效的引用时),JVM通过垃圾回收器将该对象标记为释放状态。
finalize() 方法(如果该对象定义了此方法)。垃圾回收器以
"对象可以不被垃圾回收" : JAVA, 就是能不回收就不会回收,而且垃圾回收器没有释放申请的内存, 那么随着程序的正常退出, 申请的内存会自动交还给操作系统; 而且垃圾回收本身就需要付出代价, 是有一定开销的, 如果不使用,就不会存在这一部分的开销
, 而且只能回收内存中由JAVA(堆)创建的对象所占用的那一部分内存, 无法回收其他资源, 比如文件操作的句柄, 数据库的连接等等
C++中的析构. 两者不是对应关系, 因为第一点就指出了垃圾回收的发生是不确定的, 而C++中析构函数是由程序员控制(delete) 或者离开器作用域时自动调用发生, 是在确定的时间对对象进行销毁并释放其所占用的内存
(System.gc())不一定保证垃圾回收器的运行
finalize方法
JAVAfinalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的,但是不一定会被调用,即使是进程退出前。
class A { public A() { System.out.println("A()"); } protected void finalize() { System.out.println("~A()"); } B b; } class B { public B() { System.out.println("B()"); } protected void finalize() { System.out.println("~B()"); } } public class Test{ public static void main(String[] args) { A a = new A(); B b = new B(); a.b = b; a = null; } }
A() B()
JVM执行GC的时候才会执行的,GC并没有执行,GC是否执行以及其执行的时机并不是可以精确控制的
GCʱ
class A { public A() { System.out.println("A()"); } protected void finalize() { System.out.println("~A()"); } B b; C c; } class B { public B() { System.out.println("B()"); } protected void finalize() { System.out.println("~B()"); } } class C { public C() { System.out.println("C()"); } protected void finalize() { System.out.println("~C()"); } } public class Test{ public static void main(String[] args) { //对象成员变量仍然存在引用 A a1 = new A(); B b = new B(); a1.b = b; a1.c = new C(); a1 = null; //System.gc()建议垃圾回收器进行垃圾回收,但是不一会立即执行 System.gc(); } }
A() B() C() ~C() ~A()
* finalize
(GCRoots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。
finalize
* finalize
finalize()是Object的protected方法,JAVAObject类中继承finalize()方法GC在回收对象之前调用该方法。
finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),是在对象消亡时运行的。由于C++没有垃圾回收,对象空间手动回收,所以一旦对象用不到时,程序员就应当把它delete()掉。所以析构函数中经常做一些文件保存之类的收尾工作。JAVAfinalize()的调用具有不确定性,如果内存总是充足的,那么垃圾回收可能永远不会进行,也就是说finalize()可能永远不被执行
finalize()方法需要被显示的调用,即在子类中的finalize()块中需要显示调用super.finalize(),若没有调用super.finalize()方法,超类中finalize()方法将永远都不会被调用。
* finalize方法用途
finalize()其实是用来释放不是通过JAVA的new关键字分配的内存,
- 清理本地对象(通过JNI创建的对象),比如说通过本地方法调用了C程序,C程序通过malloc分配了内存,那么垃圾回收器就不能通过JAVA语言来释放内存,只能在finalize方法内通过本地方法调用C程序进行释放内存
- 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。InputStream,为了避免用户的误操作,可以在InputStream的finalize方法中关闭流,这样为资源的释放增加了一层保护网,虽然不保证一定能够执行。