JAVA-JVM-GC垃圾回收机制

  1.GC垃圾回收内容比较多.首先我们需要先知道它的垃圾回收的范围:
在这里插入图片描述由上图可以知道GC的垃圾回收在方法区和堆,但99%的垃圾会在堆中产生!
2. 首先我们需要知道堆结构:
堆内存分为三个区域:

  • 新生区(伊甸园区)young/new

  • 养老区 old

  • 永久区 perm
    新生区:也可以再分为伊甸园区,和幸存区(有两个:from区和to区)
    堆内存结构了解完后再来解释一下各个区的意思:
    新生区
    类:诞生和成长的地方,甚至死亡

  • 伊甸园:所有的对象都是在这个区new来的

  • 幸存区,也就是伊甸园区第一个GC回收后幸存下来的

老年区:从上面三个区追踪幸存下来的
永久区:这个区域常驻内存的.用来存放一个JDK自身携带的Class对象,Interface元数据,存储的是java运行时的一些环境.或类信息.这个区域不存在垃圾回收,关闭vm虚拟就会释放这个区域的内存.
3. GC回收机制的三种算法:
引用计数器法,复制算法,(标记清除压缩算法)
(1)引用计数器法:
加粗样式计算每个对象的引用次数,清除无引用的对象,如图中灰色的对象C.

(2)复制算法
在这里插入图片描述

  如果说幸存区中from 和to都有对象存在,那么两个区就会有一个区将里面的东西复制给另外一个区,以保证两个区中有一个区的时空的就定为to区
  当一个对象经历了15次GC都还没有死就会进入养老区:-XXMaxTenuringThreshold = 15;通过这个参数可以设定进入老年代的时间,根据程序整体架构去进行调整。

分析:
在这里插入图片描述
**解析:**图中Eden区的存活下来的对象会复制到幸存区,幸存区有的对象也会复制到同一个区,这个区就变为from区,留下另一个幸存区to区为空.经过15次轻GC回收后存活下来的对象进入养老区.其他均被清除掉
上文中提到过轻GC,自然还会有一个重GC,那就是当新生区幸存区,养老区内存都满了之后,触发一次重GC,将三个区没引用到的对象清除出去.

  • 好处:没有内存的碎片
  • 坏处:浪费了一个幸存区的空间:多了一半空间(to)永远是空的,假设对象100%存活(极端问情况)
  • 复制算法最佳使用场景:对象存货都较低的时候:新生区

(3)标记清除算法
在这里插入图片描述
缺点:两次扫描,严重浪费时间,会产生内存碎片,

优点:不需要额外的空间

解决问题:标记压缩,再优化!防止内存碎片产生,再次扫面,向一段的移动存活的对象,多了一次的移动成本

在这里插入图片描述
本质就是不断再优化。

标记清除压缩:

先标记清除几次,在进行压缩
总结:

内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)

内存整齐度:复制算法=标记压缩算法>标记清除算法

内存利用率:标记压缩算法=标记清除算法>复制算法

思考一个问题:难道没有最优算法吗?

答案:没有最好的算法,但是只有最合适的.依据场景来定.----->GC:分代收集算法

年轻代:存活率低,利用复制算法最好的

老年代:存活率高,区域大.利用标记清除(内存碎片不是太多的情况下),+标记压缩混合实现

  • 轻GC和重GC分别在什么时候发生?

    轻GC在新生代内存满了的时候,也就是伊甸园区,和两个幸存区都满了之后,会触发一次轻GC,这个时候会将伊甸园区99%的对象清理掉,还有少部分的幸存区的对象。

    重GC在新生代,老年代的内存都满了之后,会触发一次重GC,重GC下手是很重的

原创文章 32 获赞 52 访问量 501

猜你喜欢

转载自blog.csdn.net/qq_42400763/article/details/105785547
今日推荐