1、什么是垃圾
所谓垃圾,就是内存中已经没用的对象。既然是“垃圾回收”,那就需要知道哪些对象是垃圾,JAVA虚拟机中根据可达性分析的算法来决定哪些对象是要被回收的垃圾
1、什么是可达性分析算法
JVM是将内存中GCRoot为起始点,从起始点开始往下搜索,搜索走过的路劲,成为引用链,最后通过判断对象的引用链是否可达来判断是否可回收,例如,某些对象和引用链是断开的,没有连接到GCRoot,说明该对象是垃圾对象,则该对象在GC的时候会被回收
3、 JVM分代回收策略
Java虚拟机根据对象存活周期不同,把堆内存分为新生代、老年代。注意: 在 HotSpot 中除了新生代和老年代,还有永久代。
4、新生代
新生代又分为三个区Eden区,Survivor0区、Survivor1区,这三区大小比例为8:1:1
1)绝大数刚刚创建的对象会存放到eden区
2)当eden区第一满的时候,会进行垃圾回收。首先将Eden区的垃圾对象回收清除 ,并将存活的对象复制到S0, 此时S1区是空的
3)下一次Eden区满了,再执行一次垃圾回收。此次会将Eden和S0区的垃圾对象回收清除,并将存活对象复制到S1,S0为空
4)如此在S0和S1区反复进行GC,每次GC还存活的对象,年龄+1,当年龄超过15的对象,就会复制到老年代
新生代GC回收算法一般采用复制算法
5、老年代
一个对象如果在新生代存活了足够长的时间而没有被清理掉,则会被复制到老年代。老年代的内存大小一般比新生代大,能存放更多的对象。
几种晋升到老年代的对象
1)长期存活对象——》就是上面提到的被Monitor GC年龄超过15次,还存活的对象
2)大对象:占用大内存的对象——》所有对象创建的时候,默认是分配到新生代的,可以通过-XX:PretenureSizeThreshold
来控制直接升入老年代的对象大小,如果对象内存大小大于这个,就会直接晋升到老年代
3)担保机制——》当新生代内存不足的时候,创建的对象直接分配到老年代
4)动态年龄机制——》当Survivor区相同年龄的对象占用内存大小超过Survivor区的内存大小,将占用内存大于相同年龄对象的内存的,复制到老年代
老年代GC回收算法标记压缩的回收算法
复制算法(Copying)
将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中。之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
标记-压缩算法 (Mark-Compact)
需要先从根节点开始对所有可达对象做一次标记,之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。最后,清理边界外所有的空间。因此标记压缩也分两步完成:
- Mark 标记阶段:找到内存中的所有 GC Root 对象,只要是和 GC Root 对象直接或者间接相连则标记为灰色(也就是存活对象),否则标记为黑色(也就是垃圾对象)。
- Compact 压缩阶段:将剩余存活对象按顺序压缩到内存的某一端。