jvm(垃圾回收)
2021-07-06 13:04:27 2 举报
AI智能生成
详细的介绍了Java虚拟机中垃圾回收的相关知识点。
作者其他创作
大纲/内容
Jvm(垃圾回收)
垃圾回收算法
标记-清除
缺点
第一个:是执行效率不可控,试想一下如果堆中大部分的对象都可回收的,收集器要执行大量的标记、收集操作。第二个:产生了许多内存碎片,通过回收后的内存状态图可以知道,被回收后的区域内存并不是连续的,当有大对象要分配而找不到满足大小的空间时,要触发下一次垃圾收集。
概要
首先标记出所有需要被回收的对象,然后对标记的对象进行统一清除,清空对象所占用的内存区域
标记-复制
优点
应用场景
1.年轻代
2.垃圾较多
标记-复制算法在大量垃圾对象的情况下,只需复制少量的存活对象,并且不会产生内存碎片问题,新内存的分配只需要移动堆顶指针顺序分配即可,很好的兼顾了效率与内存碎片的问题。
预留一半的内存区域未免有些浪费了,并且如果内存中大量的是存活状态,只有少量的垃圾对象,收集器要执行更多次的复制操作才能释放少量的内存空间,得不偿失。
标记-复制算法将内存分为大小相同的两个区域,运行区域,预留区域,所有创建的新对象都分配到运行区域,当运行区域内存不够时,将运作区域中存活对象全部复制到预留区域,然后再清空整个运行区域内存,这时两块区域的角色也发生了变化,每次存活的对象就像皮球一样在运行区域与预留区域踢来踢出,而垃圾对象会随着整个区域内存的清空而释放掉
标记-压缩
概括
1.老年代
标记整理算法解决了内存碎片问题,也不存在空间的浪费问题,看上去挺美好的。但是,当内存中存活对象多,并且都是一些微小对象,而垃圾对象少时,要移动大量的存活对象才能换取少量的内存空间。
标记整理算法的标记阶段与其他算法一样,但是在整理阶段,算法将存活的对象向内存空间的一端移动,然后将存活对象边界以外的空间全部清空
分代垃圾回收
把堆内存划分为老年代和年轻代,不同的位置使用不同的算法搭配使用。
垃圾收集器
垃圾收集器组合关系
7中经典垃圾回收器
年轻代垃圾回收器
Serial Gc
运行方式
分析
serial收集器使用复制算法、串行回收和‘stop-thw-world’机制方式执行内存回收。
简单高效(在单核cpu下)
搭配Serial old Gc(标记-整理)回收
存在问题
串行回收、stw时间长,程序卡顿时间长
使用场景
运行在client模式下的默认垃圾回收器
用户的桌面应用场景,可用内存一般不大(几十MB到一两百MB)
ParNew Gc
是Serial Gc 的多线程版本,除了使用并行回收垃圾外,两种收集器没有区别,使用标记-复制算法。
在很多jvm运行在server模式下的新生代的默认垃圾收集器
在多cpu环境下,可以充分利用CPU资源,提高程序吞吐量。但是在单CPU下,运行速度不比Serial gc高
搭配Serial old Gc垃圾回收
Parallel Scavenger Gc(吞吐量优先)
使用复制算法、并行回收和‘stop the world’机制
和parNew gc 不同之处在于,parallel Scavenga目标是达到可控制的吞吐量
自适应调节策略也是和parNew 的重要区别
JDK8中默认的垃圾回收器
高吞吐量可以高效的利用cpu时间,尽快完成程序的运算任务。常用在服务器环境中使用,例如:订单处理、工资支付等。
老年代垃圾回收器
CSM(低时延)
gc过程
初始标记(Initial-Mark)阶段:在这个阶段中,程序中所有的工作线程都将会因为“Stop-the-World”机制而出现短暂的暂停,这个阶段的主要任务仅仅只是标记出GCRoots能直接关联到的对象。一旦标记完成之后就会恢复之前被暂停的所有应用线程。由于直接关联对象比较小,所以这里的速度非常快。并发标记(Concurrent-Mark) 阶段:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。重新标记(Remark)阶段:由于在并发标记阶段中,程序的工作线程会和垃圾收集线程同时运行或者交叉运行,因此为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。并发清除(Concurrent - Sweep) 阶段:此阶段清理删除掉标记阶段判断的已经死亡的对象,释放内存空间。由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的
优缺点
concurrent mode failure
Serial old Gc
采用标记-压缩算法、串行回收和stop thw world机制
client模式下默认的老年代垃圾回收器
server模式下有两个用途
与新生代parallel Scavenge配合使用
作为老年代CMS收集器的后备垃圾收集方案
Parallel old Gc
采用标记-压缩算法、并行回收和stop the world机制
年轻代、老年代都可回收
Garbage First(G1)
G1内存模型
每个Region被标记了E、S、O和H,这些区域在逻辑上被映射为Eden,Survivor和老年代。还有第四种类型,被称为巨型区域(Humongous Region)。 Humongous区域是为了那些存储超过50%标准region大小的对象而设计的,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。
如何判断对象是否可回收?
第一种、引用计数器算法:
第二种、根搜索算法-可达性分析算法:
所谓可达性分析是指,顺着GCRoots根一直向下搜索(用一个成语概括就是“顺藤摸瓜”),整个搜索的过程就构成了一条“引用链”,只要在引用链上的对象叫做可达,在引用链之外的(说明跟GCRoots没有任何关系)叫不可达,不可达的对象就可以判断为可回收的对象。
如果对虚拟机的内存布局与运行流程有所了解的话,这些作为GCRoots都很好理解,它们是程序运行时的源头,程序的正常运行必须依赖它们,而与这些源头没有任何关系的对象,即可视为可回收对象。就好比“瓜从藤上掉下来了, 那这瓜肯定也没有用了”
可作为GCRoots对象有哪些
1.虚拟机栈帧上本地变量表中的引用对象(方法参数、局部变量、临时变量)2.方法区中的静态属性引用类型对象、常量引用对象3.本地方法栈中的引用对象(Native方法的引用对象)4.Java虚拟机内部的引用对象,如异常对象、系统类加载器等5.所有被同步锁(synchronize)持有的对象6.Java虚拟机内部情况的注册回调、本地缓存等
每当对象被引用一次计数器加1,对象失去引用计数器减1,计数器为0是就可以判断对象死亡了。这种算法简单高效,但是对于循环引用或其他复杂情况,需要更多额外的开销,因此Java几乎不使用该算法。
0 条评论
回复 删除
下一页