一、基础概念
GC(垃圾收集器)
1.1 GC三种分类
- Minor GC:新生代GC,指发生在新生代的垃圾收集动作。所有的Minor GC都会触发全世界的暂停(stop-the-world),停止应用程序的线程,不过这个过程非常短暂。
- Major GC:老年代GC,指发生在老年代的垃圾收集动作。
- Full GC:是清理整个堆空间,包括新生代和老年代。
1.2 堆的内存划分
- 新生代 ( Young ):主要用来存放新生的对象,新生代又被划分为三个区域,Eden、From Survivor、To Survivor。
- 老年代 ( Old ):主要用来存放应用程序中声明周期长的内存对象
⚠️ 注意1:
下图中的永久代(Permanent)不属于Java堆,它是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被加载的时候被放PermGen space区域
⚠️注意2:
- 堆大小 = 1/3的新生代 + 2/3的老年代
- 新生代大小 = 8/10的Eden + 1/10的from + 1/10的to
二、JVM区分新生代和老年代对象的方法
首先,JVM会为每个对象定义了一个对象年龄计数器。在分配对象时,优先将对象分配到新生代的Eden空间。当对象经过第一次Minor GC后仍然存活,且能被Survivor(To、From空间)容纳的话,就会被移动到Survivor空间中,并将对象年龄设定为1;然后,对象在Survivor区域每经历过一次Minor GC后,对象年龄计数器就加1,当对象年龄计数器达到15岁(默认年龄,也可通过参数设置)时,如果对象仍然存活,就会晋升为老年代中。
虚拟机并不是永远要求对象的年龄达到最大年龄才能晋升到老年代。对象还可以通过另外一种方式晋升到老年代,即如果在Survivor空间中,相同年龄的所有对象的内存大于Survivor空间的一半时(无法执行复制操作了),年龄大于或等于该年龄的对象就可以直接进入老年代。
三、GC触发条件
- 程序调用System.gc时可以触发
- 系统自身来决定GC触发的时机。系统判断GC是否触发的依据是根据Eden区和From Space区的内存大小来决定,当内存大小不足时,则会启动GC线程并停止应用线程
四、GC操作的对象
可以分为通过可达性分析法无法搜索到的对象和可以搜索到的对象。对于搜索不到的进行标记。
五、GC释放对象
对可以搜索到的对象进行复制操作,对于搜索不到的对象,调用finalize()方法进行释放