上一篇: Java虚拟机栈 https://mp.youkuaiyun.com/editor/html/110788112
下一篇:强引用,软引用,弱引用和虚引用 https://mp.youkuaiyun.com/editor/html/110789072
java程序在运行的时候,无时无刻都在创建对象,当一些对象已经超过相应的作用域的时候,同时在年轻代的空间不够的时候,就需要进行垃圾回收,对无用的对象进行回收,释放对应的内存。上述的运行时数据区的介绍中,堆和方法区是需要进行垃圾回收的。java虚拟机栈不用回收,pc也不用(这个没介绍),本地方法栈(跟java虚拟机栈是一样的,所以也没有介绍)也不用进行垃圾回收。
哪些对象是存活的?既然要进行回收对象,那肯定是要回收那些已经没用的对象,对运用运行没有影响的那些对象。如何判断对象是否没用并可以回收呢?
可达性分析算法
通过一系列GC Roots的根对象作为起始点,然后从这些点开始进行搜索,搜索能到的路径,能够在这些链路上的对象,都是有用对象,反之,不在这些路径的对象都是无用的对象,需要被垃圾回收的对象。
GC Roots有哪些:
比如上述讲到的java虚拟机栈中栈帧里面的局部变量表:因为没有服用掉已经超过作用域的变量,导致内存泄漏的问题。这里的局部变量表里面的变量就可以作为GC Roots。
使用yourkit 工具来查看GC Roots的类型:
package classfile;
import cn.yishijie.Person;
import cn.yishijie.Test;
import java.util.concurrent.TimeUnit;
public class ClassFile {
public static void main(String[] args) throws Exception{
// 局部变量
Person person = new Person();
person.setName("jeffchan");
person.setAge(10);
Person p1 = new Person();
p1.setName("caraliu");
p1.setAge(12);
p1.setPerson(person);
// 活着的线程
new Thread(()-> {
while (true){
try {
TimeUnit.SECONDS.sleep(1L);
}catch (Exception e){
}
}
},"jeff.chan").start();
}
}
图如下:
发现这里的GC Roots有:
1、活着的线程
2、栈本地变量对象(包含方法的参数)
3、JNI Global ( java本地接口)
4、Class 静态变量对象等
5、monitor use 被用来进行同步的对象
这里的一个对象可以属于多个类型,比如即是或者的线程,又是本地变量等的。从理论上来讲,如果要使用同步锁,那么这个锁就有可能是个静态变量对象,那么也能说明一个对象可以当作多种GC Roots的类型,不过这里我模拟不出静态变量和监控对象的场景,因为我使用静态变量时,从上述的图中,我是找不到那个变量的,如果把它当作一个监控锁,那么发现它的GC Roots的类型变成了本地变量的那种形式。