垃圾回收基础理论

垃圾

没有任何引用指向的对象都是垃圾

找垃圾的方法

  • 引用计数法:一个对象创建时会分配一个计数器,有引用指向这个对象时,计数器+1,当引用失效,计数器-1,当计数器为0时,就可以判断为一个垃圾对象(这种方法解决不了循环引用的问题)
  • 根可达算法:以GC Roots为根展开引用链路搜索,如果一个对象没有任何链路跟GC Roots关联,那么就可以判断为一个垃圾对象
    • GC Roots的对象:线程栈变量,静态变量,常量池,JNI指针(本地方法对象)

垃圾清除的算法

  • 标记清除算法:
    • 优点:标记处垃圾对象后清除,算法相对简单,存活对象多的情况效率较高
    • 缺点:两边扫描(找出有用对象,找出垃圾对象并清理)效率偏低,容易产生碎片。
  • 拷贝算法:
    • 优点:适用于对象较少的情况,只扫描一次,效率提高没有碎片
    • 缺点:空间浪费,移动复制对象需要调整对象引用
  • 标记压缩算法:
    • 优点:不会产生碎片,方便对象分配,不会内存减半
    • 缺点:扫描两次,需要移动对象,效率偏低。

堆区内存分步图

在这里插入图片描述

进入老年代年龄的参数

-XX:MaxTenuringThreshold

栈上分配

  • 线程私有小对象
  • 无逃逸(没有被外层引用)
  • 支持标量替换(使用普通类型代替对象)
  • 无需调整(不需要GC优化)

线程本地分配 TLAB(Thread Local Allocation Buffer)

  • 占用eden,默认1%
  • 多线程的时候,不用竞争,eden就可以申请空间,提高效率
  • 小对象
  • 无需调整

对象何时进入老年代

超过tenuringThreShould 指定次数(YGC)

  • Parallel Scavenge:15
  • CMS:6
  • G1:15

动态年龄

Eden和S1在GC中存活的对象,超过了S2容量的50%,年龄大的直接放入老年代

分配担保

YGC期间,有对象进来,survivor区的空间不够了,空间担保直接进入老年代

对象创建内存分步流程图

对象内存分配流程图

常见的垃圾回收器

Jdk诞生Serial追随,提高效率诞生了PS,为了配合CMS产生了ParNew,1.4后期诞生了CMS,CMS是里程碑式的GC,它开启了并发回收的过程,但是CMS毛病较多,因此目前任何一个JDK版本默认是CMS 并发垃圾回收是因为无法忍受STW

常见的垃圾回收器

  • Serial:年轻代串行回收
  • Serial Old:单线程在老年代
  • PS:年轻代,并行回收
  • ParNew:年轻代配合CMS的并行回收
  • CMS:
    • 初始标志:标记根对象
    • 并发标记:占失败80%,一遍产生垃圾,一边标记
    • 重新标记:STW
    • 并发清理:会产生浮动垃圾

缺点:内存碎片化,浮动垃圾 解决方案:降低触发CMS阈值-XX:CMSinitiation Occupancy Fraction92%减少到65%甚至更低,保证老年代有足够的空间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章