jvm 垃圾回收详解
如何定位垃圾
1.reference count 无法解决三个对象循环指向,全部是垃圾
2.root search 根搜索方法
回收的算法
1.Mark-Sweep(标记清除)
碎片化,内存不连续
2.Copying(拷贝)
内存一分为二只用一半,内存浪费
3.Mark-Compact(标记压缩)
有用的覆盖垃圾
Garbage Collectors(垃圾回收器)
G1是逻辑分代,物理不分代
除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型
除此之外不仅逻辑分代,而且物理分代
Serial 年轻代 串行回收
PS 年轻代 并行回收
ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)
CMS问题比较多,所以现在没有一个版本默认是CMS,只能手工指定
CMS既然是MarkSweep,就一定会有碎片化的问题,碎片到达一定程度,CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收
新生代 = Eden + 2个suvivor区
1. YGC回收之后,大多数的对象会被回收,活着的进入s0
2. 再次YGC,活着的对象eden + s0 -> s1
3. 再次YGC,eden + s1 -> s0
4. 年龄足够 -> 老年代 (15 CMS 6)
5. s区装不下 -> 老年代
老年代
1. 顽固分子
2. 老年代满了FGC Full GC
java -XX:+PrintCommandLineFlags -version 查看当前jdk使用的垃圾回收器PS+PO
垃圾收集器跟内存大小的关系
1. Serial 几十兆
2. PS 上百兆 - 几个G
3. CMS - 20G - -三色标记 + Incremental Update - Remark
4. G1 - 上百G 三色标记 + SATB
5. ZGC - 4T - 16T(JDK13)ColoredPointers(颜色指针)
Epsilon -啥也不干(测试,确认不用GC参与就能干完活儿)
-Xms<size> 设置初始 Java 堆大小
-Xmx<size> 设置最大 Java 堆大小
java -XX:+PrintFlagsWithComments 显示所有-XX的参数,只有debug版本有
java -XX:+PrintFlagsFinal 最终值
java -XX:+PrintFlagsInitial 打印所有参数 初始值
java -Xms200M -Xmx200M -XX:+PrintGC com.hy.T15_FullGC_Problem01
jps 列出正在执行的java进程
jstack 20089 打印线程栈
jinfo 20089 线程虚拟机信息
jstat -gc 20089 显示各个区被占用了多少
arthas阿里jvm调优工具
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
遇到被之前线程占据解决方法
find / -name arthas 查找路径
cd /root/.arthas/lib/3.3.6/arthas
java -jar arthas-client.jar 进入上次的session
shutdown
解决正常工作
dashboard 指令查看线程,cpu,内存情况
jvm 指令 jvm详情,以及使用的垃圾回收算法
thread 把这个java进程所有的线程显示出来
thread 11 显示11号详情
thread -b 查看死锁线程
sc *com.hy* 查看类,所有类或者指定类
sm *com.hy* 查看方法,把类下面的所有方法列出来
trace classname methodname 跟踪方法执行时间
monit 跟踪方法运行数据,那些值被传进去,那些值被返回
设定日志参数
1. -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
2. 或者每天产生一个日志文件
jmap
jmap -histo 10086 查看哪些对象在不断的占内存(揪出对象进行分析)
jmap -histo 10086 | head -20 (堆比较大的情况使用该命令,堆就会暂停,项目不能正常运行)
四种说法可以说用过jmp
1.很多服务器备份(高可用),停掉一台不影响其他服务器
2.设定参数HeapDump, OOM会自动产生堆转储文件 (小公司) ,大公司会有监控。内存增长就会报警
jmap -dump:format=b,file=xxx pid :
java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError com.hy.T15_FullGC_Problem01
使用MAT / jhat /jvisualvm 进行dump文件分析
https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
jhat -J-mx512M xxx.dump
http://192.168.17.11:7000
拉到最后:找到对应链接
可以使用OQL查找特定问题对象
arthas dump
下载文件使用java visualVM查看分析
3.测试环境压测
4.在线定位 arthas观察,先有怀疑点,使用arthas去观察具体类的具体方法,代码
arthas王炸功能,反编译
jad(可以查看当前版本自己的代码是否被覆盖)
jad com.hy.T15_FullGC_Problem01
查出问题,下一步环境直接改代码生效,并且不会暂停业务,不用替换jar包
(限制条件:属性不支持,方法名不支持)
redifine 指令线上改代码生效
操作步骤
1.修改.java代码正确
2.将.java代码编译成.class文件,可以使用编译工具,可以使用javac javac TT.java
3.将.class文件上传至对应环境对应目录
4.启动arthas,redefine .class立即生效 redefine /root/IdeaProjects/jvmtiaoyou/src/com/hy/TT.class
CMS 边工作边标记,
三色标记算法
未标记白色,
已标记但是成员变量没有标记灰色
已标记并且成员变量全部标记则是黑色
第一种可能
标记完灰色,指向的一个对象不指向了,则原来指向的成了垃圾,没有意识到。floatgarbage 浮动垃圾,下一轮回收
第二种可能 incrementupdate
一个对象没有被标记也就是白色,原来指向他的不指向他了,黑色的标记过的指向它了,则实际不是垃圾,但是黑色的指向它不会进行重新扫描,则会误认为他是垃圾。
处理方案,将原来标黑的对象标灰。写屏障
第三种可能
并发标记,多个线程进行回收
此对象两个成员变量r1,r2,线程1标记完r1发现没有指向,然后线程2将r1指向一个白色对象,此时此对象会变成灰色,线程2标记完r2,线程1标记完r2发现没有指向,就会直接把此对象变成
黑色,也就是标为垃圾。就会产生误标
最终stw,remark重新标记
G1方案
SATB Snapshot At the Beginging

浙公网安备 33010602011771号