JVM垃圾回收

文章目录

  • 一、为什么有垃圾回收
  • 二、确定垃圾
    • 1.什么是垃圾
    • 2.如何找垃圾
    • 3.如何判断有无引用指向
      • 引用计数
      • 可达性分析
  • 三、释放垃圾对象
    • 1.标记清除
    • 2.复制算法
    • 3.标记整理
    • 4.分代回收

申请一块内存是明确的,使用前肯定要申请。但是内存释放是不明确的,释放的时机不确定。只有彻底不用了才能释放。在java中通过JVM自动判定释放时机。
在java中,释放内存的主要区域是堆上,所以释放内存等于释放对象。

一、为什么有垃圾回收

当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。

垃圾回收分成两个主要的阶段:确定垃圾和释放垃圾对象。

二、确定垃圾

1.什么是垃圾

后续再也不用的对象。

2.如何找垃圾

如果一个对象,没有任何引用指向它,此时这个对象一定是无用的。则可确定为垃圾。

3.如何判断有无引用指向

引用计数

(在java中不使用这种方法。)

给对象安排一个额外空间,用来保存一个整数。这个整数表示指向这个对象的引用数量。

JVM垃圾回收_第1张图片

缺陷:
1.浪费内存空间
2.可能会造成循环引用的问题

可达性分析

(java使用的方法)

把对象之间的引用关系理解成了树形结构。从根节点(GC Roots)出发,只要能遍历到的就是可达,遍历不到的就是不可达。

JVM垃圾回收_第2张图片
缺陷:
1.消耗时间
2.在遍历的时候,需要按照一定的顺序,如果在遍历的时候,引用关系发生了变化,就很麻烦。需要在遍历的时候,让其他业务暂停。(STW问题)

关键要点:
起点(root)的确定。
1.栈上的局部变量
2.常量池引用的对象
3.方法区中静态成员引用的对象

三、释放垃圾对象

1.标记清除

把垃圾进行标记,并且把标记的内存空间进行释放。

JVM垃圾回收_第3张图片
如上图所示,标记的区域就是垃圾,直接把这些区域进行释放就好了。

缺陷:
会产生内存碎片。
因为在申请空间时,是连续的。但是现在空闲的区域是独立的。
比如我想申请一块大小×××的内存空间,这些独立的空间大小的总和足够,但是单独却不够,所以无法申请。进而造成资源浪费。

2.复制算法

将内存空间分成两段。一次只用一半

JVM垃圾回收_第4张图片
解决了内存碎片的问题。
缺陷:
1.内存利用率低;
2.如果垃圾很少的情况,复制成本很高。

适用于垃圾很多,要保留的很少的情况。

3.标记整理

标记垃圾,把后面的控价整体前移。类似于顺序表,删除元素的思想。

JVM垃圾回收_第5张图片

解决了内存碎片的问题
缺陷:
搬运开销太大。

4.分代回收

JVM最终选择的方法。针对不同情况,使用不同的方法。

通过设置年龄,表示这个对象存活的时间。刚诞生的对象,年龄为0岁。
每扫描一次,如果这个对象还没有被淘汰,年龄就增长一岁。

JVM垃圾回收_第6张图片

1.刚出生的对象,放在伊甸区内,对伊甸区进行第一轮GC扫描(可达性分析),淘汰掉垃圾,通过复制算法把要保留的放入幸存区。
2.幸存区也分成了两个大小均等的部分。一次只用一半。每次扫描,都从其中一半中淘汰垃圾,把要保留的通过复制算法拷贝到另一半中。
3.当这个对象经过层层扫描,年龄已经增长到一定程度了,就会通过复制算法拷贝到老年代中。
4.进入老年代的对象,被淘汰的概率很低,GC扫描频次会低很多。针对老年代中的垃圾,通过标记整理进行处理。
5.特殊情况:如果对象非常大,直接进入老年代。大对象复制成本太高。

以上就是JVM垃圾回收的常见内容了!祝大家顺顺利利健健康康天天开心,下次见!!!

你可能感兴趣的:(jvm)