阅读 1240

Java对象的销毁、你真的知道吗?

本文正在参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。​

在日常的开发中、我们都知道,Java的内存清理是通过垃圾回收器进行的,那么其是如何将没用的对象被被清理掉的呢?

Java 语言的内存自动回收称为垃圾回收(Garbage Collection)机制,简称 GC。垃圾回收机制是指 JVM 用于释放那些不再使用的对象所占用的内存。

Java对象在使用后需要清理。 对象清理是释放该对象所占用的内存。 在创建对象时,用户必须使用new操作符为对象分配内存。 清除对象后,系统会自动回收内存,不需要用户进行额外的处理。 这也是Java语言的一个特性,它使程序员更容易管理内存。

一般一个对象被当作垃圾回收的情况主要如下两种。

1)对象的引用超过其作用范围。

{
    Object o = new Object();    // 对象o的作用范围,超过这个范围对象将被视为垃圾
}
复制代码

2)对象被赋值为 null

{
    Object o = new Object();
    o = null;    // 对象被赋值为null将被视为垃圾
}
复制代码

在 Java 的 Object 类中还提供了一个 protected 类型的 finalize() 方法,因此任何 Java 类都可以覆盖这个方法,在这个方法中进行释放对象所占有的相关资源的操作。

那么问题又来了,finalize()是个什么鬼呀,既然会调用对象的这个方法就说明所有的类都会有这个方法(毕竟所有的类都会被回收嘛),自然而然我们就想到了java的根类 Object.进去看看?

protected void finalize() throws Throwable { }
复制代码

最后一行还真找到了,是一个实现为空的方法,既然是protected就说明具体的方法可以留给子类去实现之前我们说过只有当对象不再被任何引用指向时候,该对象才会被回收。那么真的是这样吗?我们举个栗子看看

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()方法,在销毁前如果一个人的前还没花光,打印这个人是失败的,否则这个人是成功的。下面是我们在main()中的代码

public class Test {
public static void main(String args[]){
User u1=new User(200);
new Object();
new User(100);

}

}
复制代码

运行结果居然什么都没有!运行结束之后不光有引用指向的u1,就连没有任何引用指向的new User(100);居然都没有被回收。这是怎么回事呢?

我们来看看Thinking In Java中是怎样解释的

java中的并非总是被垃圾回收,也就是说对象可能不被回收。一般程序只要不到濒临存储空间用光,垃圾回收器一般都不会主动回收内存,如果程序结束,并且垃圾回收器一直没有释放你创建的空间,则随着程序的退出,资源则会被归还给操作系统。所以上面的我们finalize()才一直没有被调用

如果我们想看到效果,可以通过如下方法:

public class Test {
public static void main(String args[]){
User u1=new User(200);

new Object();

new User(100);

System.gc();

}

}
复制代码

System.gc();会强制系统垃圾回收器工作,运行效果会出现error

说明new User(100);创建的对象被回收了。

注意:调用 System.gc() 或者 Runtime.gc() 方法也不能保证回收操作一定执行,它只是提高了 Java 垃圾回收器尽快回收垃圾的可能性。 

知识补充:

在 Java 虚拟机的堆区,每个对象都可能处于以下三种状态之一。

1)可触及状态:当一个对象被创建后,只要程序中还有引用变量引用它,那么它就始终处于可触及状态。

2)可复活状态:当程序不再有任何引用变量引用该对象时,该对象就进入可复活状态。在这个状态下,垃圾回收器会准备释放它所占用的内存,在释放之前,会调用它及其他处于可复活状态的对象的 finalize() 方法,这些 finalize() 方法有可能使该对象重新转到可触及状态。

3)不可触及状态:当 Java 虚拟机执行完所有可复活对象的 finalize() 方法后,如果这些方法都没有使该对象转到可触及状态,垃圾回收器才会真正回收它占用的内存。

好了、今天就分享到这儿吧,我是小奥、下期见~~

打卡 文章 更新 80/  100天

文章分类
后端
文章标签