极客大学java进阶第2课
JVM核心技术-JVM命令行工具
-
java Java应用的启动程序
-
javac JDK内置的编译工具
-
javap 反编译class文件的工具
-
jps/jinfo 查看java进程
- -lmv 进程详情
-
jstat 查看JVM内部gc信息
- -gc
- -gc
-
jmap 查看heap或类占用空间统计
- -heap 打印堆内存
- -histo 看哪些类占用的空间最多
-
jstack 查看线程信息
-
jcmd 执行JVM相关命令
-
jjs 执行js命令
JVM图形化界面
jconsole
jvisualVM
JMC(官方最强大的工具)
GC要关注单位时间内创建的对象数量
- 飞行记录器:关注一段时间内内存使用情况
GC的背景与一般原理
为什么会有GC:内存有限,
内存泄露:对象未被使用,但还一直存在
- gc算法
- 标记
- 标记清除:遍历所有可达对象,并在内存中分门别类记下.标记完成后,不可达对象清除后在之后的内存分配时可以重用
- 压缩整理:整理内存,是内存连续
- 老年代::经过多次gc而没有被回收的年轻代的对象 * -xx +MAxTenuringThreshold=15
- 对象分配在eden区,标记阶段eden区的存活对象就会被复制到存活区(因为eden区存活的时间会比较短,所以采取复制的方式).老年代默认都是存活的对象,采用移动的方式
- 标记可达对象那个
- 删除不可达对象
- 整理老年代空间中的内容,方法是将所有的存活对象赋值,从老年代空间开始的地方依次存放
- 根对象:当前执行的方法的局部变量和参数,活动线程,静态字段,JNI(底层)引用
串行gc和并行gc
串行GC(Serial GC\ParNewGC)
串行gc对年轻代使用标记-复制算法,对年老代使用标记-清除-整理算法.会触发STW停止所有的应用线程.
-XX: UseSerialGC
-XX: +USeParNewGC 配合CMS使用
并行GC
年轻代和年老代的垃圾回收会触发STW,年轻代使用标记-复制算法,年老代使用标记-清除-整理
- 在GC期间,所有CPU内核都在并行清理垃圾,暂停时间短
- 在两次GC周期的间隔期,没有GC线程在运行,不会消耗任何系统资源.
并发GC(CMS)
新生代::标记-复制.
老年代::标记-清除
- 不对老年代整理,使用空闲列表来管理内存
- 标记-清除阶段的大部分工作和应用线程一起并发执行.
CMS的6个阶段 - 初始标记:标记根对象和子引用
- 并发标记::标记引用
- 并发预处理:
- 最终标记(STW)
- 并发清除
- 并发重置
G1 GC
- 目标:将STW停顿时间变成可预期和可配置的
- 事实上,G1 GC是一款软实时垃圾回收器,可以将其设置某项特定的性能指标。为了达成可预期的停顿时间指标,G1有一些独特的实现
- 首先,堆不在分成年轻代和老年代,而是划分为多个(2048)可以存放对象的小块堆区域。每一个小块,可能一会被定义成eden区,一会被定义成survivor区合起来就是年轻代,所有的old区拼在一起那就是老年代。
- -XX:+UseG1GC -XX:MaxGCPauseMillis=50 每次暂停时间最大50ms
- G1以增量处理
- 每次STW都会收集所有年轻代的内存块,但一般只包含部分老年代.
- 在并发阶段估算每个小堆块存活对象的总数,构建回收原则:垃圾最多的小块会优先被处理
- G1处理步骤
- 年轻代模式转移暂停
- 并发标记
- 转移暂停:混合模式
- G1退化为Serial
- 并发模式失败
- 晋升失败:没有足够的内存供存活的对象使用,由此触发full gc
- 巨型对象分配失败
GC对比
GC组合
- serial+serial old 实现单线程的低延迟垃圾回收机制
- parNew+CMS,实现多线程的低延迟垃圾回收机制
- Parallel Scavenge和Parallel Sacvenge Old,实现多线程的高吞吐量垃圾回收机制
GC算法选择
- 如果系统考虑吞吐优先,CPU资源都用来处理业务,用parallel GC
- 如果系统考虑低延迟优先,每次GC时间尽量短,用CMS GC
- 如果系统堆内存较大,同时希望整体来看平均GC时间可控,使用G1
总结
- 串行GC(Serial GC):
- 并行GC(ParNew,Parallel Scavenge,parallel old):多线程并行地执行垃圾回收
- CMS:多线程并发标记和清除
- G1
- ZGC:通过着色指针和读屏障,实现超低延迟