java 内存垃圾回收机制
1. 堆内存结构
- 年轻代: (包含eden,s0,s1) 此区域主要是存储新创建或新创建不久的对象
- 老年代 : 用来存储存活时间比较久的对象
- 永久代: 保存类的信息以及其他一些高级特性,如字符串池 。 注:JDK 8 开始把类的元数据放到本地堆内存(native heap)中,这一块区域就叫 Metaspace
2. YongGC (minor gc) 过程:
触发原因: 当Young gen的 eden 区满的时候。
使用的算法: 复制算法
发生STW
-
GC过程:
当应用启动后,当一个对象创建并被分配时,如果此时年轻代的s0,s1内存还未被使用,并且eden的空间足够使用,此时对象存储在eden区域。
-
随着系统的运行,java创建的一些对象不断的分配到堆中eden的剩余空间不断的变小,当eden的空间不足与分配新创建的对象时,触发垃圾收集器收集,eden区被标记存活的对象复制到s0并且对象的年龄+1为1,未被引用的对象随着eden 区域的清理而被删除。
-
当eden满时进行下一次YGC时,eden的被标记对象移动到s1区域此时对象年龄加1为1,s0的被标记的对象移动到s1,因为上次s0对象的年龄为1所以这次年龄加1为2,eden和s0的未标记对象将被清空。
-
等到下一次YGC时重复上次动作,eden对象复制到s0,s1对象复制到s0,然后它们的年龄+1,eden和s1的空间被清空,也就是所说的两个s区互换。
-
当年轻代的对象,这里指s区年龄到达一定年龄时,年轻代里的对象将被移动到老年代
年轻代收集器: 这里先讨论下面三款年轻代收集器(G1下次讨论)
区别 \ 名称 | Serial 收集器 | ParNew | Parallel Scavenge收集器 |
---|---|---|---|
是否多线程 | 单线程串行 | 多线程并发 | 多线程并行 |
能和哪些老年代配合使用 | CMS , SerialOld | CMS , SerialOld | Serial Old,Parallel Old |
优势 | 单核cpu效率比较高 | 能充分利用多核cpu的优势 | 系统的吞吐量 |
- 收集过程
-
serial :
-
parnew:
-
Parallel:
- 所带来的影响: young gc 中有 可能 部分存活对象晋升到老年区 , 所以young gc后 old gen的内存空间 通常 有所提升
3. Old GC (回收过程):
- 由于能回收老年代的收集器有 cms ( Concurrent Mark Sweep),Parallel Old ,serial old (单线程) 注:G1下次讨论
区别 \ 名称 | Serial Old | Parallel Old | cms |
---|---|---|---|
使用算法 | 标记整理 | 标记整理 | 标记清除 |
串行、并行、并发 | 串行 | 并行 | 并发 |
使用场景 | 单CPU环境下的Client模式、CMS的后备预案 | 在后台运算而不需要和客户端太多交互的任务 吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合 | 互联网站或者B/S系统的服务端上,希望服务的响应速度,系统停顿时间最短 |
- cms 收集器运行过程
- 初始标记(CMS initial mark): 发生STW ,标记GCRoots关联的对象,速度很快,应用线程暂停
- 并发标记(CMS concurrent mark): 进行GC Roots Tracing的过程,在整个过程中耗时最长。
- 重新标记(CMS remark): 重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
-
并发清除(CMS concurrent sweep)
参考: 深入理解java虚拟机 , oracle 文档