垃圾回收
1.对象和垃圾回收
Java的垃圾回收的java语言重要的功能之一,当程序创建对象,数组,或者引用对象,系统都会在内存中为其分配一个空间,对象就是保存在这个内存区域中,当这块内存区域不再被任何变量引用,这个内存就变为垃圾,等待垃圾回收机制进行回收。
垃圾回收具有以下特点:
- 垃圾回收机制只负责回收堆内存中的对象,不会回收任何物理资源(比如数据库连接,网络,IO等)
- 程序无法精确的控制垃圾回收的运行,垃圾回收会在合适的时候进行,当对象永久性的失去引用,系统会在合适的时候回收它所占的内存。
- 在垃圾回收机制回收任何对象之前,都会调用它的finalize方法,该方法可能使该对象重新复活,从而导致垃圾回收机制的取消。
1.1对象在内存中的状态
当一个对象在堆内存中运行的时候,根据它引用的状态,可以把它所处的状态分为三种情况:
- 可达状态:当创建一个对象后,如果有一个以上的引用变量引用它,则这个对象处于可达状态,程序可以通过对象的实例变量和方法进行调用。
- 可恢复状态:如果程序中的某个对象不再有任何引用变量引用它,它就进入到了可恢复状态,在这个状态下,系统的垃圾回收机制准备回收这该对象所占的内存。,在回收该对象之前会调用该对象的finalize方法,看是否还有其他变量引用,如果有可以由可恢复状态进入到可达状态。
- 不可达状态: 当对象与所有引用变量的关联都被切断,并且系统已经调用该对象的finalize方法也无法进入到可达状态, 从而导致进入不可达状态, 系统才会进行垃圾回收。
案例分析:
public class StatusTest {
public void test() {
/**
* 当执行下方代码:定义一个变量a,并且执行内存的"Spring入门基础"字符串
* 此时"Spring入门基础"处于可达状态
*/
String a=new String("Spring入门基础");
/**
* 创建了一个新的对象 "redis基础"字符串对象
* 让a变量引用这个 "redis基础"字符串对象,此时"Spring入门基础"这个字符串
* 对象没有任何变量引用 ,进入到可恢复状态。分析可知此时 "redis基础" 是可达状态
*/
a=new String("redis基础");
}
}
![1ae0bdc744e28f12ec7536c5558bef26.png](https://img-blog.csdnimg.cn/img_convert/1ae0bdc744e28f12ec7536c5558bef26.png)
1.2强制垃圾回收
当一个对象失去引用后,系统何时调用它的finalize方法执行资源清理,何时会进入到不可达状态,
对于程序来说,程序员无法精准的控制系统何时进行垃圾回收,也无法明确在什么时间进行垃圾回收,程序只能控制一个对象不再被任何变量引用,绝不能控制它在何时被垃圾回收。
虽然程序无法精准的控制垃圾回收,但是依然可以通过代码指定系统进行强制垃圾回收。但是系统执行垃圾回收仍然是不确定的,大部分时候程序员只能指定强制垃圾回收,但是在何时进行还是由jvm自身决定。
系统有如下方式可以进行强制垃圾回收:
- 调用System类的gc方法
- 调用Runtime类的gc方法
public class GcTest {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
GcTest gc = new GcTest();
/**执行强制垃圾回收.. 一旦执行垃圾回收 系统会调用这个对象finalize方法看
* 是否可以进入到可达状态虽然指定了强制垃圾回收 ,但是系统会自己觉得什么时候
* 执行垃圾回收.. -->System.gc();
*/
Runtime.getRuntime().gc();
//java -verbose:gc GcTest 这个命令详细查看垃圾回收的执行
}
}
/**
* 分析:按理来说强制执行应该是循环执行五次,但从结果显示可知System.gc();并不是立即执行
* finalize方法,而是通知系统进行垃圾回收,但具体什么时候执行还是要由系统自行决定
* 调用了System.gc()进行垃圾回收,但由系统自行决定执行的时间或者是执不执行,因此每次运行
* 结果输出的次数都会小于5(调用的次数)
*/
@Override
protected void finalize() throws Throwable {
System.out.println("系统正在执行清理GcTest这个对象....");
}
}
1.3 Finalize方法
在垃圾回收机制回收某个对象所占用的内存,会调用这个对象的finalize方法。
Finalize方法有4个特点:
- 不要主动调用某个对象的finalize方法,把该方法交给垃圾回收机制自动执行
- Finalize方法何时被调用,是否被调用 都是不确定的,不要把finalize方法当做一定会执行的方法。
- 在jvm执行可恢复对象的finalize方法 可以使该对象或者系统中的其他对象重新进行到可达状态
- 当jvm执行finalize 如果出现异常, 垃圾回收并不会报告异常,程序可以继续执行。
public class FinalizeTest {
private static FinalizeTest ft=null;
public void info()
{
System.out.println("系统正在执行垃圾回收....");
}
public static void main(String[] args)
{
//1.创建FinalizeTest对象,没有任何变量引用 ,进入到可恢复状态
new FinalizeTest();
//2.通知系统进行强制垃圾回收,但不一定会立即执行finalize方法
System.gc();
//3.强制垃圾回收机制 调用可恢复对象的finalize方法,此时ft便初始化完成
System.runFinalization();
//4.ft初始化完成,便可执行info方法
ft.info();
}
public void finalize() {
ft=this;
}
}
2.自我提升
自我学习,了解垃圾回收的算法。至少掌握三种以上。