GC垃圾回收

1:GC

回收区域:堆和方法区(线程共享的区域存在垃圾回收,线程私有的区域不存在垃圾回收)

栈是线程销毁才会回收,栈帧是某次方法调用后返回才销毁(自动回收,无需GC)

Java语言不用程序员自己分配内存,也不需要自己回收内存,原因就是JVM中实现的垃圾回收机制(自动回收)

方法区:保存静态变量和类信息,很少回收,比如老版本的JVM就不会回收方法区,所有会产生内存泄漏

堆:回收的主要区域

发生GC的时间:对象进入老年代或者新生代,如果该区域空间不足则会触发该区域的GC。

新生代GC:minorGC,采取复制算法,效率比较高

老年代GC:majorGC,标记清除算法,标记整理算法,效率比较差

1:死亡对象的判断算法

1:引用计数算法

给对象增加一个引用计数器,当有一个地方引用它,则+1,当引用失效-1,任何时刻当计数器为0则不能在被引用,即对象已死,变成垃圾。

JVM没有采取这种方式,无法计算循环引用问题

2:可达性分析算法

GC Roots:垃圾回收要检查的根节点

引用链:某个对象到GC Roots的路径,对象间的引用关系表现出的连接关系

不可达对象:一个对象到GC Roots是不可达的,就是一个垃圾

2:垃圾回收算法

1:老年代回收算法-----标记清除算法

流程:先将需要回收的对象一个一个进行标记,再对标记的对象一个一个进行删除

效率问题:效率不高,标记和回收时需要进行遍历

空间问题:回收后产生大量不连续的内存空间,内存碎片

2:新生代回收算法-----复制算法

流程:将内存区域划分为两个大小相等的空间,在回收时,将存活的对象复制到另外一块未使用的内存空间中,清除之前使用的空间

使用场景:大多数对象具有朝生夕死的特性(很多方法调用,使用局部变量等于new的对象,方法执行结束这些对象即可回收),新生代对象符合朝生夕死的对象

空间问题:空间利用率只有50%

新生代回收算法的改进:

JVM中新生代的回收算法是基于复制算法的优化版本,因为新生代的对象很多都是朝生夕死的,所以并不需要按照1:1划分内存,而是将新生代分为较大的Eden(伊甸园)和两块较小的Survivor(幸存者)空间,ES比为8:1,空间利用率达到90%。每次只使用伊甸区和其中一块幸存区,称为from区,另一个幸存区称为to区。回收时,将from区存活的对象复制到to区,再清理from区。如果一个对象再两个存活区交换15次,则会放入到老年代。

3:老年代回收算法-----标记-整理算法

流程:标记存活对象,将存活对象往一侧移动,然后清除端边界另外一半的空间

4:分代算法

流程:JVM采取的算法,本质上没有具体算法实现,只是通过区域划分,实现不同区域的不同垃圾回收策略

将内存(堆)划分为新生代,一个E区,两个S区,以及老年代。

针对新生代采取改进的复制算法,老年代使用标记清除或者标记整理算法。

新生代和新生代:

一般创建的对象放入新生代,但是大对象(对象占据的空间超出JVM设置的阈值)创建后进入老年代。新生代中连续交互15次的对象。新生代GC时,分配担保失败的对象(8+1中存活的对象放到另外一个1中,如果放不下则放入老年代)

3:垃圾回收器

新生代收集器:

  • Serial
  • ParNew
  • Parallel Scavenge

老年代收集器:

  • Serial Old
  • Parallel Old
  • CMS

全堆收集器:

  • G1

垃圾回收线程:守护线程,可并行执行,用户线程可以和垃圾回收线程并发执行或者等待(STW,Stop the world)

吞吐量:执行用户代码时间/(执行用户代码时间+垃圾回收时间),表达出一个程序的效率好不好

1:CMS垃圾收集器—老年代

Concurrent Mark Swap:并发标记清除

1:老年代收集器

2:标记清除算法

3:用户体验优先,垃圾回收线程和用户现场同时执行,存在局部的STW(少许时间暂停用户线程)

4:并发收集,低停顿

CMS搭配新生代的ParNew收集器,以此给用户更好的体验

收集过程:

  • 初始标记:标记GC Roots能直接关联的对象(这个阶段需要STW)
  • 并发标记:进行GCRoots引用链追踪的过程,搜索引用路径(这个阶段可以和用户线程并发)
  • 重新标记:修正并发标记阶段,和用户线程并发执行时,修复标记产生变动的记录(这个阶段需要STW)
  • 并发清除:并发清除垃圾,和用户线程并发

缺点:

  • 对CPU资源比较敏感(可能产生CPU不足的问题)
  • 无法处理浮动垃圾(是第四阶段时用户线程并发执行时产生的垃圾)
    • 需要预留空间给浮动垃圾
    • 不知道具体预留空间大小,如果浮动垃圾超出预留空间大小则产生失败 Concurrent Model Failure (并发模式失败)
    • 超出预留空间则会再次触发一次老年代的GC,且是Serial Old单线程的收集器回收
  • 标记清除算法本身的空间碎片问题的产生,且可能导致提前触发GC
2:G1垃圾收集器—全堆的垃圾回收器

使用G1收集器时,堆的内存划分:划分为一个一个的region区,动态分配为E区(伊甸),S区(幸存),T区(老年)

特性:

  • 全堆收集器
  • 整体看基于标记-整理算法,局部看是基于复制算法
  • 用户体验优先的收集器

新生代回收步骤:回收多个E区和S区,复制存活对象到空的region,再重新定义为S区

老年代回收步骤:

  • 初始标记阶段:标记GC Roots能直接关联的对象(这个阶段需要STW),可以和新生代GC同时执行

  • 并发标记:进行GCRoots引用链追踪的过程,搜索引用路径(这个阶段可以和用户线程并发),优先回收(Garbage First)存活率低或者几乎没有存活的region

  • 最终标记阶段:修正并发标记阶段,和用户线程并发执行时,修复标记产生变动的记录(这个阶段需要STW)

  • 筛选回收阶段:筛选存活率低的region,可以和新生代GC同时执行

2:JMM

JMM:Java内存模型,用来屏蔽各种硬件和操作系统的内存访问差异,实现让Java程序在各平台下能达到一致的内存访问效果

中间内存:属于硬件层面的中间内存,而不是JMM的概念

主存:存放线程共享的数据

工作内存:存放线程私有的,以及共享变量的拷贝

8大原子性的字节码指令:用于主存和工作内存的数据读取操作

Java内存模型的三大特性:

  • 原子性:八大字节码层面的原子性指令,基本数据类型的访问具备原子性
  • 可见性:当一个线程修改了共享变量的值,其它线程能够可见
  • 有序性:本线程内观察,所有的操作都是有序的,在另一个线程观察所有操作是无序的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值