您的位置:首页 > 其它

初始化与清理之二(清理)

2016-11-05 21:04 155 查看

前言

初始化往往是程序员调用方法前所必须做的事情,但对象用完之后的清理却常常忽略。对于清理,java中提供了垃圾回收器机制,通常情况下不必由程序员关心如何清理的问题;垃圾回收机制在便利的同时也引发两个问题:一是垃圾回收器只能回收由new分配的内存空间,对于一些特殊内存分配方式,是无法回收的;二是内存回收是一个自动的过程,可能发生也可能不发生,如果java虚拟机在并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以回收内存。

工作机理

对于上述第一种情况,在java中一切皆对象,那什么是非new方式分配内存呢?这样的情况主要发生在使用“本地方法”(用于调用非java代码的方式,目前只支持C和C++)的情况下,可能利用malloc这种方式分配了内存;为了这种情况,java允许在类中定义finalize()方法,垃圾回收器一旦准备清理某对象,先调用其finalize()方法,然后在下一次垃圾回收时回收其内存。

对于第二种情况,我们无法要求垃圾回收器立即回收对象,普通的清理工作只能定义普通java方法,明确的调用它来做一些清理工作。

finalize()的特殊用法

finalize()可以用作对终结条件的判断,虽然不是肯定会被调用,这样就有可能使得某些程序缺陷被发现。

问题

当对象被回收时,是否会先回收其内部所含对象?

class A {
private B b;
private C c;

public A(B b) {
this.b = b;

}
public void setC() {
c = new C();
}
public C getC() {
return c;
}

@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
System.out.println("A finalize");
}
}

class B {
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
System.out.println("B finalize");
}
}

class C {
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
System.out.println("C finalize");
}
}

public class clean {
public static void main(String[] args) {
// 被引用 答案是不会
/*B b = new B();
System.out.println("1-------------------");
System.gc();// 建议jvm回收内存,并不一定会执行回收操作
// 引用置为null 答案是会
b = null;
System.out.println("2-------------------");
System.gc();
*/
// A对象回收时如何做
//      new A(null).getC();//A先 C后
//      new A(null);//C先 A后
new A(null).setC();//C先 A后
System.out.println("3-------------------");
System.gc();
// A对象有引用,B对象是否会被回收 答案是不会
/*
* A a = new A(new B()); System.out.println("4-------------------");
* System.gc();
*/
}
}


结论:

1.当对象回收时,如果其内部对象没有在其他地方引用,那么会先回收其内部对象

2.将对象引用置为null或其他对象,原引用对象就引用数就会减少

3.方法内部创建的引用变量,在整个方法执行链(指方法调用其他方法这样一个嵌套调用)结束后,该引用变量才会释放引用

4.内部对象被返回时,就算返回值没有被其他引用变量所持有,内部对象也会后于外部对象回收,其原因是有中间引用???(暂时不明确,留待以后)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: