马士兵老师公开课真的讲的挺好的,不过自身水平不够,整理一下自己听课的感觉
JVM调优 垃圾回收
垃圾:当有一个对象没有任何引用指向
java通过垃圾回收器,一般不需要关心,运行线上系统的时候需要了解
reference count 不能解决循环引用的问题
root searching 根可达算法(main方法里面直接能访问的对象):线程栈变量,静态变量,常量池,JNI指针
实际上是找有用的对象,找不到的就是垃圾
Mark-Sweep 标记清除 特点:碎片化,效率比较高
copying 把内存一分为二 特点:效率特别高,占空间
Mark-Compact 标记压缩,有用的压缩到最前面 特点:不会产生碎片,方便对象分配,效率比较低
堆内存逻辑分区 不同垃圾回收器不同的模型,多数使用分代模型,年轻代(young),old(老年代),一般为1:2,新生代(eden,survivor,survivor)8:1:1
一个对象从出生到消亡 首先到eden区(使用copying),经过一次GC,会去S1(Survivor1),想到马超的皮肤幸存者(*^_^*),经过又一次复制到surivor2,默认15次,到old,通过参数MaxTenuringThreshold配置,old区一般使用Mark-Sweep和Mark-Sweep
具体要学姐的博客https://blog.csdn.net/qq_40550018/article/details/88533564
首先new一个对象的时候,优先在栈上分配(符合特定的条件),(垃圾回收器不用介入),如果可以栈上分配,就pop出去,栈上分配不了会分析是否对象很大,直接进入Old区使用FGC
对象不大,如果适合放在eden区就TLAB(Thread Local Allocation Buffer)线程本地分配,GC清除了就结束,要不然去S1或者年龄够了去S2,结束
G1逻辑分代,物理不分代
ZGC和shenandoah 逻辑,物理不分代
Epsilon jdk11以后
cmd里面输入可查询垃圾回收器 java -XX:+PrintCommandLineFlags -version
常见的Serial 和Serial Old :a stop-the world(STW墙面呆着就是所有都停止的时候),copying collector which uses a single GC thread
翻译:停止世界,copy算法的单线程的
parallel : a stop-the world,copying collector which uses multiple GC threads(多线程的情况)
垃圾回收器与内存息息相关,当内存小的时候,STW可以,但是当内存大时,需要并行的,当垃圾越来越多,多到一定数量级,web服务是无法忍受的(工作中可能STW三天以上),游戏服务器有些维护(通过重启一次),12306就是在备份维护数据重启
新的垃圾回收器的引入:改进STW就是CMS(concurrent mark sweep)并发垃圾回收
STW时间短:工作现场不断找到垃圾,初始标记使用根可达算法找到最根上垃圾,不接着往下找了
最消耗时间使用的是并发标记,可能会产生冲突,所以通过重新标记,时间也不长,最后并发清理
面试:并发标记漏标怎么办,三色标记算法,白色,灰色(自身被标记,成员变量未被标记),黑色
CMS最大的问题在于会产生碎片,但是碎片太多的时候,这时候转化使用serial Old,单线程
G1 jdk1.9以后使用
ParNew与Parrallel Scavenge等价
总结:一般无特殊组合:现在是:Parrallel Scavenge和Parrallel Old组合(PS+PO)
如果追求更小的STW,使用ParNew+CMS
垃圾内存碎片太多的时候诞生了G1(大概可以几百个G)
ZGC可以解决更大的内存
G1之前,物理内存分为年轻代和老年代
G1分为大小相同的块(物理上分区逻辑上分代),例如eden区可以变为Old区,互相之间可以变来变去,可以回收一部分区域(STW时间可以不用这么长),有些块在工作,有些在回收,整个过程与CMS区别不大
ZGC和Shenandoah正在开发中,号称1ms之内,赶上C++的效率
发展方向:内存越来越大,STW越来越短
JVM优化:无监控不优化,优化的目的(吞吐量和响应时间优先两种情况),使用的手段
面试题:什么是调优?主要两个点:优化运行JVM运行环境(慢,卡顿);解决JVM运行过程中出现的各种问题(OOM)
例如:原来内存1.5G,停顿时间5s,升了内存后,停顿时间变成15s,为什么,怎么调?
老年代太大了,得换垃圾回收器
银行风控系统(银行回收风险,个人信息存入数据库,计算产生值给予多少额度)
cardInfo个人信息;getAllcardInfo拿出一部分数据来
modelfit看模型是否符合
固定线程池做运算,scheduledThreadPoolExecutor,每做一个线程modelfit,线程停顿
这个代码可能出现out of memory(内存溢出)
面试题:ThreadLocal为什么会产生内存泄漏?
top命令,不断刷新,占多少CPU过高的时候,运维会告诉你
jps(有哪些java在运行)
jstack观察3271有几个线程,但不是很详细规范,主要关注有没有waiting很长时间的,或者占CPU比较高的,在线调优非图形化,jstack观察是否产生了死锁,waiting on condition,解决不了OOM
jstat -gc 不断产生日志,一般不适用这个命令
jinfo 3271 读出来3271进程的常用信息,没有垃圾回收器信息,也不常用
面试题:UseCompressedClassPointers和UseCompressedOops
用的最多的:
arthas