运行数据区

GC Roots
- 虚拟机栈中引用的变量(本地变量)
- 方法区中类的静态属性(类的静态属性)
- 方法区中常量引用的对象(常量)
- 本地方法栈中引用的变量 (本地方法)
垃圾收集算法
- 标记-清除算法
- 缺点: 标记-清除效率都不高,且内存空间容易产生碎片化,分配较大内存对象时,不得不进行垃圾收集动作
- 复制算法
- 优点: 不会出现碎片化等情况,实现简单,运行搞笑
- 缺点: 需要2倍内存,如果存活的对象较多时, 效率变低
- 应用: 商业虚拟机用复制算法来回收新生代的内存,因为新生代的对象存活率低,因此不需要1:1分配内存,Hotspot 虚拟机分配比例为eden:survivor:survivor=8:1:1
- 标记-整理算法
- 标记过程和“标记-清除”一样,但不是直接对可回收对象进行清除,而是对存活的对象向一端移动,然后清理掉其他的内存
- 分代收集算法
- 描述: 根据对象存活的周期,将java堆分成新生代和老年代,根据年代的特定,采用适当的收集方法。
- 新生代: 每次垃圾收集时,有大量的对象死去,只有少量的存活,所以采用复制算法,调节适当的比例。
- 老年代: 对象比较稳定,存活率较高,没有多余的空间,所以比较适合用”标记-整理”或“标记-清除“算法。
Minor GC和Full GC区别
- Minor GC:新生代GC,回收比较频繁,速度比较快
- Full GC: 老年代GC也称为Mojor GC,回收比较慢,效率低
堆内存分为几块
堆内存分为新生代和老年代 永久代(hotspot中在方法区,元空间?)
内存分配策略
- 对象优先分配在Eden
- 大的对象直接进入老年代
- 长期存活的对象 (年龄达到15)
- 动态对象年龄判断(survivor中相同年龄的对象总和大于survivor空间一半的时候,直接进入老年代)
- 空间分配担保 (老年代的连续空间大于新生代所有对象总和?是否担保?连续可用空间是否大于历次进入老年代的平均?否则Full GC)
垃圾收集器
-
Serial收集器 (复制算法)
单线程完成垃圾收集工作,并且暂停其他所有的工作线程。对比其他单线程来说,简单高效,没有线程切换的开销。 -
ParNew收集器(复制算法)
相当于多线程的Serial收集器,能和CMS配合工作 -
Parallel Scavenge收集器(复制算法)
目的是达到一个可控制的吞吐量 -
Serial Old收集器 (标记-整理)
Serial 老年代版本。 -
Paraller Old 收集器 (标记-整理)
Paraller Scavenge 的老年代版本 -
CMS收集器(标记-清除)
一种以获取最小回收停顿时间为目标的收集器。
清理过程分为四个步骤:- 初始标记
- 并发标记
- 重新标记
- 并发清除
其中初始标记和重新标记停止所有工作线程。并发标记是GC Roots Tracing过程,重新标记则是为了修正并发标记期间因工作线程继续运作而导致的变动。并发清除,清除掉标记上的内存。
三个缺点:1.对cpu资源敏感,默认回收启动的线程数为 (cpu数量+3)/4 ,当cpu数量较少时,占用cpu资源较多。2. 无法处理浮动垃圾,由于并发清理阶段工作线程还在运行,运行过程中会产生垃圾,只能等下一代GC被清理,且CMS需要预留一点空间,在并发收集时使用。3. 会产生大量碎片,由于并发-清除算法。 -
G1收集器
优势- 并发与并行: 利用多线程的资源,减少停顿时间
- 分代收集: 采用不同的方式收集新对象和旧对象
- 空间整合: 整理上标记-整理,局部复制算法,不会产生空间碎片
- 可预测的停顿: 可以指定时间用来收集垃圾
不考虑Remembered Set操作,分为几个步骤
- 初始标记
- 并发标记 (耗时较长,但不需要停顿用户线程)
- 最终标记
- 筛选回收
网友评论