Java虚拟机的垃圾回收机制
Java语言会对程序运行过程中产生的垃圾进行自动回收,不需要我们手动地写语句主动地对垃圾进行回收。
什么是垃圾?
在C语言中不再被使用的内存空间被称为垃圾,因为在C语言中如果我们使用到一些自定义类型的结构体,我们就需要自己手动地开辟内存空间,例如:假设自定义类型的结构体名称叫做Node
Node* p = (Node*)malloc(10*sizeof(Node));// 意思为开辟10个内存大小为Node类型的空间,并将开辟成功的空间的首地址进行返回
当我们对这个结构体使用完并且确保不会再次被使用后,就需要使用free函数将开辟的内存空间给释放掉,如果不进行手动地释放,那么手动开辟的空间就会一直占用内存,最终有可能导致内存溢出。
在Java语言中不再被任何引用所指向的对象被称为垃圾,这也是非常容易理解的,因为我们在对对象进行创建时,就需要给出一个对象引用变量用于指向我们在堆内存中创建的对象,所以如果一个对象没有被任何引用变量所指向的话,那么我们也就获取不到对象,也就没有办法对对象进行操作,这个对象自然就成了垃圾。
为什么需要回收垃圾?
由于垃圾会占用一定的内存空间,如果不对垃圾进行回收就会导致内存中存在越来越多的垃圾,使得内存空间溢出,所以需要对垃圾进行回收。
Java虚拟机中的垃圾回收机制,我们需要先找到垃圾,然后才能对垃圾进行回收。
由于垃圾是指不再被任何引用所指向的对象,所以垃圾回收的区域在堆内存中
垃圾回收算法
垃圾标记阶段算法
使用垃圾标记阶段算法,需要在堆内存中通过某些算法找出哪些对象已经成为了垃圾
引用计数算法
堆内存中创建对象的对象头中存在int类型的counter计数器,当存在引用指向对象时,计数器加1,当引用不再指向对象时计数器减1,当计数器中的值为0时,表示该对象没有被任何引用所指向,该对象就成为了垃圾,Java虚拟机在进行垃圾回收时就会根据counter计数器的值进行判断对象是否为垃圾。
引用计数算法判断对象是否为垃圾时比较方便快捷只是根据计数器中的值进行判断,但是会在每个对象的对象头中添加属性占用额外的空间,并且引用变量每一次指向对象都需要对对象的属性进行更新操作,占用大量的时间。
循环引用问题
循环引用是指存在两个或两个以上的对象中的变量互相指向其他对象,例如存在A类对象拥有B类型的成员变量,B类对象拥有A类型的成员变量,如下代码所示。
public class A {
public B b;
}
public class B {
public A a;
}
首先创建A,B两个对象a,b,然后给对象中的成员变量进行赋值。
A a = new A();
B b = new B();
a.b = b;
b.a = a;
这就是循环依赖,对象之间的变量相互指向其他对象,如下图所示。
但是为什么会说循环依赖存在问题呢?
可达性分析算法