深入理解JVM虚拟机----垃圾回收

垃圾回收的主要内容就是
1.什么样的对象该回收,如何判断
2 回收哪里,
3 怎样回收
4 什么时候回收
5 垃圾收集器

一对象回收可回收的判断标准

1 引用计数法:给对象一个引用计数器,没当有一个引用的时候计数器加1
优点:实现简单
缺点:没法解决循环引用

2可行性分析法:从一个GCRoot出发,进行图的深度遍历。
问:什么的对象可以选取为GCRoot?

答:局部变量表,本地缓存如包装类Integer,常量池,Class对象的属性
问:那这么多GCRoots,改如何选呢?
答:1栈的全遍历,JVM开始从一些已知位置(例如说JVM栈)开始扫描内存,实现简单,但是十分耗时。
2 就是时间换空间,某个时候把栈上代表引用的位置全部记录下来,这样到真正 gc 的时候就可以直接读取,而不用再一点一点的扫描了。事实上,大部分主流的虚拟机也正是这么做的,比如 HotSpot ,它使用一种叫做 OopMap 的数据结构来记录这类信息。而且精准。在GCRoot枚举的时候是会有Stopworld;
问:什么是安全点和安全区域
答:OopMap不是在任何时候都会去更新OopMap,这样会浪费很多内存,而是在特点的位置记录这个,来更新OopMap。这样的点不能选取太少,让GC收集器等太久,也不能选的太多,以至于频繁的更新oopMap加大内存。选取的一般是方法调用,或者循环这类地方作为安全点。还有就是在GC发生时如何让所有线程跑到最近的安全点。安全区域是对安全的点扩展,在安全区域内是不会发生引用关系的改变。在某些时候,线程是没法执行的(例如slepp或者阻塞),在线程进入安全区域的时候会有一个标志,离开的时候回取消标志。
问:抢占式中断和主动式中断的区别
答:抢占式中断,在GC时让所有线程都中断,当发现有线程没有到达安全点事会让它继续执行,这样比较浪费是GC时间
主动式中断,就是让线程循环去访问一个中断标志,如果中断标志是1,则会跑到最近的安全点。
问:并发的可达分性如何保证正确的(如何解决对象消失问题)
1在进行并发标记的时候,用户线程修改对象的引用导致,本该消失的对象没有被回收。这就产生了浮动垃圾。
2 还有一种就是对象消失,用户线程修改了对象引用,但是被标记为要回收。解决这个问题有2个方法
1)增量更新:把线程的更新记录下来,然后在重新标记中进行修正,从记录中的对象开始遍历(CMS垃圾回收器就是这样工作的)
2)原始快照:把线程的更新记录下来,然后把删除记录的对象标记为灰色,在重新标记中进行修正,从灰色对象开始遍历(G1收集器)

二回收算法

1标记清算法:先标记在清除
优点:实现简单
缺点:容易产生内存碎片
2标记复制法:空出一片空间,标记后把活的对象移到另一边
优点:没有内存碎片
缺点:浪费空间
3标记整理法:把活的对象全部移到一起
优点:没有内存碎片,空间利用率高
缺点:有stopworld,且实现复杂
目前的JVM都是采用分代收集,不同的年龄段采用不同的算法

三收集器

1 Serial 单线程收集器:会有stopWorld
2 ParNew 并发收集器:并发收集器也会有StopWorld
3 Parallel Scavenge 吞吐量收集器:吞吐量= 用户代码运行时间/(GC+用户代码运行时间)
4Serial old 老年代收集器
5 paraller old 老年代并发收集器
6CMSCMS(Concurrent Mark Sweep)收集器
是一种以获取最短回收停顿时间为目标的收集器。采用 标记-清除 算法。
整个过程需要4个步骤:
初始标记:需要“Stop The World”,标记一下GC Roots能直接关联到的对象,速度很快。
并发标记:是进行GC Roots Tracing的过程。
重新标记:需要“Stop The World”,修正并发标记期间,用户程序继续运行而导致标记产生变动的那一部分标记。停顿时间稍长,但比初始标记短。
标记清除:和用户线程并发的收集垃圾清理工作。
由于CMS在并发清除的时候无法解决浮动垃圾(并发标记和并发清理中产生的死亡对象)会导致进行一次StopWorld的FullGC,而且CMS是才用标记清除法会导致内存碎片,最终会触发FullGC
7G1收集器:
G1收集器将整个堆划分成多个相同大小的独立区域(Region),并维护一个优先列表,用于跟踪记录每一个Region的回收价值(根据回收获得的空间大小以及回收所需的时间确定),每次在允许的时间内,优先回收价值最大的Region(这就是Garbage-First名称的由来)。它代表 Humongous,这表示这些 Region 存储的是巨型对象(humongous object,H-obj),当新建对象大小超过 Region 大小一半时,直接在新的一个或多个连续 Region 中分配,并标记为H。
虚拟机为了防止G1收集器扫描全部Region或者其他收集器扫描新生代以及老年代。G1中Region的对象引用以及其他收集器新生代与老年代之间的对象引用,虚拟机使用Remembered Set(RSet)来避免进行全堆扫描。
G1运行大致可以分为:
1、初始标记:标记一下GC Roots能直接关联到的对象。
2、并发标记:从GC Roots开始进行可达性分析。
3、最终标记:修正并发标记期间用户程序运行导致的标记变动。
4、筛选回收:进行Region的回收价值排序并进行垃圾回收
(比较复杂------待更新)

四JVM调优
1 对象有限在Eden区分配
2 大对象直接分配在old区(可以配置)
3 经历过一定次数的的对象会 被移动到old区(默认15次,可以调整)
4 动态年龄:如果s区相同年龄的对象综合大于s区一半的话,则年龄大于这个年龄的对象直接进入old区
5空间担保:再进行minorGC,old区是否有一块大小大于平均晋升到old区的连续空间,如果有则进行minorGC,否则进行FullGC
6如果经常进行FullG:可以考虑是否是eden区太小,Old区太小或者,设定的年龄门槛太小。

你可能感兴趣的:(java)