2.垃圾收集器和内存分配策略
2.1 垃圾回收方法
- 引用计数法
优点:实现简单,效率比较高,
缺点:很难解决对象的循环引用的问题 - 可达性分析算法
- 原理: 使用GC Roots 的对象作为起点,从这些节点向下搜索,走过的路径被称为应用链,如果对象没有被这个引用链引用,就判定为需要被回收的对象。
- GC Roots:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(native方法)引用的对象
- 引用类型(缓存系统中的应用场景)
- 强引用:引用存在,不会被回收
- 软引用:系统在发生内存溢出前,清理这部分对象
- 弱引用:生存到下次垃圾回收前,当垃圾收集工作时候,都会回收掉 只被 弱引用 关联的对象
- 虚引用:不能通过引用找到实例信息,为对象设置虚引用的唯一目的, 能够在这个对象被收集时,收到一个系统通知。
- 对象回收经历
经历两次标记过程
可达性分析后,筛选出需要被回收的对象,第一次标记,并筛选出覆盖了finalize 方法的对象并且没有被执行过
对象如果 finalize 方法重新关联到了引用,被移除垃圾回收的集合,否则对象被回收。 - 方法区回收
1、废弃的常量(例如 没有被应用的字符串“abc”)
2、无用的类
2.2 垃圾收集算法
标记-清除算法
特点:分为标记、清除 两个阶段。效率不高,产生内存碎片
复制算法(新生代)
将存活的对象复制到未被占用的内存中。效率快。不产生内存碎片。缺点:浪费一小块内存,存活对象较多时,效率低
标记-整理算法(老年代)
标记
将存活的对象移动到一端,删除边界以外的内存
2.3 垃圾收集器
概念:
吞吐量= 运行代码时间/运行代码时间+垃圾回收时间 虚拟机运行100 分钟,垃圾回收1分钟。则吞吐量 = 99%
停顿时间:垃圾回收时候,会暂停用户执行代码进程,单独执行垃圾回收的时间段。
浮动垃圾: 并发阶段,用户产生的新垃圾。
Serial 收集器(JDK1.3.1之前新生代收集器 复制算法)
特点:单CPU 效率高。Client 模式下可用
ParNew 收集器(新生代 ,Serial 收集器 的多线程版本 复制算法)
特点:多CPU 效率高。
Parallel Scavenge 收集器(新生代、复制算法)
特点:吞吐量优先收集器。可以开启自适应调节策略。
Serial Old 收集器 (老年代)
Paraller Old 收集器 (老年代、并行)
CMS 收集器(获取最小停顿时间为目标的收集器,标记-清除算法、老年代)
- 初始标记 :GC Root 直接关联到的对象
- 并发标记 :同用户进程一起。标记Tracing 的过程
- 重新标记 :修正并发标记过程中的标记信息
- 并发清除 : 通用户进程一起,清除垃圾
- 缺点:
- 占用资源执行垃圾回收,当CPU 数量小。更加明显。默认是 (CPU + 3)/4 。当两个cpu时候,会有一半线程执行垃圾回收。
- 无法处理浮动垃圾:CMS 默认老年代使用68%被激活。可以适当提高该参数,但如果调的太高。 -XX: CMSInitiatingOccupancyFraction 。导致大量的 Concurrent Mode Failure 。启动 Serial Old 收集器,性能降级。
G1收集器
特点:
并行并发
分代收集:不需要配合其他收集器
空间整合
可预测停顿
步骤
初始标记
并发标记
最终标记
筛选回收
2.4 理解GC日志
参数:-XX:+PrintGCDetais
例子:
33.125: [GC [DefNew: 3324k ->152k(3712k),0.000233 secs] 2234k->152k(3712k),0.00034 secs]
33.125: jvm 启动开始计时的时间
[GC (Full GC): 垃圾收集的停顿类型
[DefNew: 发生区域。
3324k ->152k: GC 前区域使用容量、GC 后区域使用容量(该区域总容量)
2.5 内存分配与回收策略
概念:
Minor GC (GC) 新生代GC 。速度快、频繁
Full GC、Major GC 老年代GC 。速度慢,伴随一次 Minor GC。时间是Minor GC是10倍以上
对象优先在Eden分配。新生代。 如果该区域内存不足,发起一次Minor GC
大对象直接进入老年代。
-XX:PeteneSizeTheshould 。(Parallel Scavenge 收集器没有这个参数)默认3 M (3145728)
长期存活的对象进入老年代
每个对象都有年龄计数器,每经历一次MinorGC 年龄 + 1 。当年龄到达指定值时候(默认值15),进入到老年代。
使用-XX:MaxTeningTheshould 设置该年龄值。
动态对象年龄判断
如果Survivor 空间中相同年龄所有对象 的大小总和 大于 该空间的一半,则大于等于该年龄的对象 直接进入到老年代。
空间分配担保
发生Minor GC 前 。先检查老年代 最大连续可用内存 >? 新生代对象大小的和
如果小于,查看HandlePomotionFaie 设置,是否允许担保失败
如果是,检查历次年轻代回收到老年代对象大小的平均值,如果平均值小于老年代剩余空间,那么尝试进行一次Minor GC,
如果HandlePomotionFaie 设置成不冒险,则进行一次full GC