本文内容为JVM垃圾收集器及算法,并不涉及具体方法实现原理,如需深入了解算法原理,请参考《深入理解Java虚拟机》,周志明先生著。由于G1收集器没有大规模投入商用,本文亦未有涉及,如需了解请参考Oracle官方文档。本文所有内容均基于Hotspot虚拟机。
如有疑惑请发送邮件至: tienchen1990@hotmail.com
一.Java内存管理
Java虚拟机在运行Java程序的时候会将其管理的内存划分为不同的数据区域。每个区域都有自己的用途,创建,使用,销毁时间各不相同。根据Java 7标准,Java虚拟机可以将内存划分为以下几个部分。
1.程序计数器(Program Counter Register):各线程私有,独立存储。在cpu分配时间片的时候, 是当前线程在执行字节码的行号指示器。字节码解释器工作时依赖于改变计数器的值来完成指令的执行,分支,跳转,循环,异常处理,线程恢复等。多线程的时间片轮转也需要。如执行的是Java方法,则记录的是虚拟机字节码指令地址。如果是Native方法则为undefined(注意此处是唯一不会抛出OOM的地方)
2.Java虚拟机栈(Java Virtual Machine Stack):线程私有。即Java方法执行的内存模型,每个方法的执行都会创建一个栈帧(Stack frame),每个方法从调用到执行结束对应一个栈帧的入栈出栈。
3.Java堆(Heap):线程共享。此内存区域存放对象实例,是垃圾收集管理器的主要工作区域,也称GC堆。还可细分为新生代和年老代。也是本文主要讨论的地方。
4.方法区(Method Area):线程共享。存放已被虚拟机加载的类信息,常量,静态变量,即时编译后的代码等。(约等于永久代 Permanent Generation)
5.本地方法栈(Native Method Stack):与虚拟机栈作用类似,使用的是Native方法。虚拟机栈执行的是Java方法,也就是字节码服务。本地方法栈使用的是Native方法服务
6.运行时常量池(Runtime Constant Pool):用于存放编译期间生成的字面量和符号引用。也可存储运行时新的常量。例:String的intern()方法
7.直接内存(Directory Memory):参考NIO的直接内存。
二. GC类型分析
Java的GC分为Full GC和Minor GC
Full GC: 针对整个新生代,年老代,元空间(metaspace ,Java8以上取代perm gen永久代)的全范围GC
Minor GC:新生代GC
三.垃圾收集器
1.Serial 串行收集器.
最古老,最稳定
简单高效
可能产生较长停顿
-XX:+UseSerialGC
新生代,年老代都会采用串行
新生代复制算法,年老代标记整理
一般运行在Client模式
并发收集器:
2.ParNew Serial收集器的并行版本
Serial收集器新生代的并行版本
多线程,需多核支持
-XX:+UseParNewGC
新生代并行
年老代串行
-XX: ParalleGCThreads 限制线程数量
3.Parallel Scanvenge
类似于ParNew, 更关注于吞吐量
-XX:+UseParallelGC
新生代并行
年老代串行
4.Parallel Old
是Parallel Scanvenge的年老代版本
-XX:+UseParallelGC
新生代并行,年老代并行
-XX:MaxGCPauseMills 最大停顿时间,单位毫秒 GC保证回收时间不过设定值
-XX:GCTimeRatio 0-100取值范围 垃圾收集时间占总时间占比 默认99,即运行最大1%时间做GC
以上所有收集器进行垃圾回收的时候都需要stop-the-world
5.CMS收集器
CMS收集器(Concurrent Mark Sweep:并发标记删除) 以获取最短停顿时间为目标. 适合于互联网站或者B/S系统服务器. 重视响应速度,希望系统停顿时间最短
Concurrent Mark Sweep 并发标记清除,并发低停顿
标记-清除算法
并发阶段会降低吞吐量(停顿时间减少,GC频率会变高)
年老代收集器(新生代采用ParNew)
-XX:+UseConMarkSweepGC 打开 (此处并发指的是与用户线程一起执行)
CMS运行过程:
初始标记 根可以直接关联到的对象,速度快..GC ROOT可达(和用户线程一起)
并发标记, 主要标记过程,标记全部对象
重新标记, 由于并发标记时,用户线程仍在运行,因此在正式清理前,再做修正
并发清除,基于标记结果,直接清理对象(和用户线程一起)
初始标记和重新标记时,需要stop-the-world
思考题:CMS收集器为何不采用标记整理算法?
如何解决碎片问题?
-XX:+UseCMSCompactAtFullCollection Full GC后,进行一次整理. 整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理
-XX: ParallelCMSThreads 设定CMS线程数量