(1)垃圾回收概述
前面我们学了堆,里面有一个垃圾回收的机制
(2)判断垃圾_引用计数
指只要有一个对象被其他变量所引用,我们就让这个对象的计数加1,有个一变量不在引用,让它的计数减一,当这个对象的计数变为0的时候,说明没有变量引用它了,那么他就可以作为一个垃圾进行一个回收,但是引用计数存在一个弊端:存在循环引用问题:
a对象引用b对象,b对象的引用计数为1。b对象引用a对象,a对象的引用计数为1,但是没有谁用再引用他们啦,是不是以为这他们俩可以被垃圾回收呢了,答案是不行,因为他们的引用计数都为1虽然这两个对象都不会再使用了他们的引用计数不能归零导致不能被垃圾回收,造成了内存上的泄露
派森虚拟机采用的是这种算法但是我们Java虚拟机既不会采用这种算法:而是采用可达性分析
(3)判断垃圾_可达性分析_根对象
可达性分析呢需要首先确定一系列根对象,根对象是哪些肯定不能别当做垃圾的对象,我们称之为根对象,在垃圾回收之前我们会对堆内存中的所有对象进行一遍扫描,看看每一个对象是不是刚才提到的根对象所直接或者间接引用,如果被直接或间接的引用过,就不能被回收
通过一个工具可以查看根对象:
MAT工具需要跟jmap工具一起使用 ,MAT需要jmap工具配合jmap先把内存快照抓取下来,才能使用MAT工具进行进一步分析
使用jps:查看一下进程id:
先需要使用jmap工具把内存快照抓取下来,转储成一个文件:dump文件的参数=b为二进制,live:为抓取哪些存货的对象,live在抓取之前进行一个垃圾回收,file:抓取的的内存快照 存成一个文件
执行到2再抓取一下,存为另外一个文件:
打开MAT工具:选择抓取的快照文件:
有一个显示图:对内存占用多的对象有哪些
还可以查看抓取的快照的根对象有哪些
分为以下类:
(1)System Class:系统类,是由启动类加载器加载的类,核心的类,
(2)java虚拟机在执行一些方法调用时去调用操作系统的方法,操作系统方法在执行时所引用的一些java对象,也是可以作为根对象
一些活动线程:活动线程中正在使用的一些对象不能当做垃圾的
线程运行时由一个个的方法调用组成,每次方法调用嫩都会产生一个栈帧,栈帧内所使用的一些东西可以作为根对象
主线程内:栈帧内用到的变量的情况,他们用到的一些局部变量,这些局部变量所引用的对象,都可以作为根对象,局部变量时存在栈帧里的new 的对象是存在堆里的,根对象是指堆中的哪些对象而不是栈帧里的局部变量引用
比如代码中创建的ArrayList集合对象
(3)Java对象中有个同步锁机制,Syschorlnize关键字如果对一个对象加了锁,被加锁的对象不能被当做垃圾的,正在加锁的对象作为根对象
第二个存储文件:
当19行list局部变量为null ,不在应用ArrayList对象了,因为我们执行了jamp:里面有live参数,它会主动执行一次垃圾回收,它会把不在引用改的Arraylist对象回收掉了,所以在根对象列表中就没有ArrayList对象了