一、JVM【JDK8】
1.1 JVM结构图
1.2 GC Roots的理解
思路就是通过一系列名字为“”GC Roots“”的对象作为哦起点,开始向下搜索,如果一个对象到GC Roots没有任何引用链连接时候,则说名对象不可用。也即给他一个集合的引用作为跟出发,通过引用关系遍历对象图,能被遍历到的对象被判断为存活,没有的话就是死亡。
可以作为GC Roots的对象
虚拟机栈中的对象 方法区中的类静态属性引用的对象 方法区中常量引用的对象 本地方法栈中Native引用的对象
1.3 JVM调优的标配参数和X,XX参数
标配参数:
java -version
java -help
X参数:【了解】
-Xint: 解释执行
-Xcomp: 第一次使用编译成本地代码
-Xmixed:混合模式【默认的】
XX参数:
Boolean类型
-XX:+或者-某个属性值,+代表开启,-代表关闭
如何查看是否开启了某个参数
jps -l jinfo -flag PrintGCDetails 4526 // 结果如下: -XX:+PrintGCDetails 表示激活了打印GC信息
KV设置类型
-XX:属性key=属性值value
如何设置元空间的大小???
jps -l jinfo -flag MetaspaceSize 6350 // 默认21M -XX:MetaspaceSize=21807104 // 程序运行调成1G -XX:MetaspaceSize=1024m
jinfo举例
-Xms: -XX:InitialHeapSize
-Xmx:-XX:MaxHeapSize
1.4 JVM初始默认值
1.5 JVM常用调优参数
-Xms: -XX:InitialHeapSize 初始堆内存【存储空间】
-Xmx:-XX:MaxHeapSize 最大堆内存
-Xss:-XX:ThreadStackSize 设置单个线程栈空间的大小,一般默认为512k-1024k【运行空间】
一般0为出事的默认值
**-Xmn:**设置年轻代的大小
-XX:MetaspaceSize 设置元空间的大小,元空间不在虚拟机中,而是使用的是本地内存,仅受本地内存的限制。默认使用了20m左右
-XX:+PrintGCDetails 打印垃圾回收的细节情况
// 模拟产生OOM的情况下,查看垃圾回收的细节 JVM配置 -Xms:10m -Xmx:10m -XX:+PrintGCDetails 程序设置50M大小的对象 byte[] byteArray = new byte[50 * 1024 * 1024];
GC类型:
FullGC:
-XX:SurvivorRatio
-XX:NewRatio
-XX:MaxTenuringThreshold 设置垃圾回收的最大年龄
二、强、软、弱、虚引用
2.1 强引用Reference
当内存不足的时候,对于强引用对象,就算是出现OOM也不会对该对象进行回收。把一个对象赋值给一个引用变量,这个变量就是一个强引用。该对象的以后永远不会被JVM回收,经常造成内存泄漏OOM。
如果没有引用才可以被回收。
2.2 软引用SoftReference
当内存足够不回收,不够就要回收,尽量不要OOM。
结果:一个null 一个 有值
当内存不够用时候呢?
配置小内存,大对象试试
结果:就发生了OOM,后面两个输出均为null
2.3 弱引用WeakReference
只要有弱引用就会回收,不管内存够不够用。
java.lang.ref.WeakReference
结果:后两个全为null
2.4 虚引用PhantomReference
形同虚设,与其他引用均不同,并不会决定对象的生命周期。
必须与引用队列联合使用ReferenceQueue
跟踪回收的状态。
三、GC垃圾回收
3.1 垃圾回收算法
1.引用计数
2.复制:内存开销
3.标记清除 :内存碎片
4.标记清除整理
3.2 垃圾回收器
这是垃圾回收算法的实现
1.Serial 串行垃圾回收器
他为单线程环境设计的只是用一个线程进行垃圾回收,会停止所有的用户线程
JVM参数:-XX:+UseSerialGC
开启后默认在Serial(Young区用) + Serial Old(Old区用)的收集器组合
新生代和老年代都会使用串行收集回收器,新生代使用复制算法,老年代使用标记-整理算法
2.Parallel 并行垃圾回收器
多个垃圾回收线程,用户线程暂停,适合于科学计算,大数据等弱交互场景。
就是串行回收器的并行版本
JVM参数:-XX:+UserParNewGC
ParNew(Young区用) + Serial Old的组合,新生代使用赋值算法,老年代使用标机-整理算法
3.CMS 并发标记清除垃圾回收器
用户线程和垃圾回收线程,不一定并行或者交替,适合于高并发场景。
JVM参数:-XX:UseConcMarkSweepGC
【养老区】:
无法整理空间 碎片
4.G1
将堆内存分割成不同的区域然后并发的随其进行垃圾回收
JVM参数:-XX:+UseG1GC
横跨young old
面向服务器的收集器
更高的并发
更少的延迟
整理空间更快
不需要很大的堆内存
不会产生很多内存碎片
用户可以指定停顿时间
目标为取代CMS
jdk7中有G1,jdk9中变成默认的垃圾回收器来替代CMS
总结:
1: G1能充分利用多CPU、 多核环境硬件优势,尽量缩短STW。
2:G1整体上采用标记-整理算法,局部是通过复制算法,不会产生内存碎片。
3:宏观上看G1之中不再区分年轻代和老年代。把内存划分成多个独立的子区域(Region),可以近似理解为一个围棋的棋盘。
4:G1收集器里面讲整个的内存区都混合在一-起了 ,但其本身依然在小范围内要进行年轻代和老年代的区分,保留了新生代和老年代,但它们不再是物理隔离的,而是一部分Region的集合且不需要Region是连续的,也就是说依然会采用不同的GC方式来处理不同的区域。
5: G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制 准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
3.3 如何查看默认的垃圾回收器?
最后一个参数就是垃圾回收器的种类
java -XX:+PrintCommandLineFlags -version
3.4 JVM的Server/Client模式
- 32位windows 默认是Client的JVM模式
- 其他操作系统2G内存,2cpu以上的用Server模式
- 64位 仅仅Server
3.5 JVM GC+Springboot部署调参
启动流程
springboot工程
maven clean
maven package
微服务启动,同时配置JVM GC的调优参数【内,外】
java -jar springbootxxxxx.war/jar
调参公式:
java -server JVM参数 -jar springbootxxxxx.war/jar
示例如下
// 1.参数调优 java -server -Xms1024m -Xmx1024m -XX:+UseG1GC -jar springbootxxxxx.war/jar // 2.查看进程ID jps -l // 3.查看信息 jinfo -flags 9969
四、Linux生产服务器变慢如何诊断?
操作步骤:
4.1 整机:top
或者 uptime 也可以
load average: 1.52, 0.98, 0.55
计算负载高: (1.52+0.98+0.55)/3 * 100% > 60%
4.2 CPU: vmstat
// 每2秒采样一次 一共采样3次 vmstat -n 2 3
// 所有的CPU idle空闲虑 mpstat -P ALL 2 // 详细信息 pidstat -u l -p 5103
4.3 内存:free
// 内存 MB单位 free -m // 查看额外 采样次数2S pidstat -p 5103 -r 2
4.4 硬盘:df
// 简单方便 GB df -h
4.5 磁盘IO: iostat
iostat -xdk 2 3 // 磁盘块设备分布 rkB/s每秒读取数据量kB; wkB/s每秒写入数据量kB: svctm /O0请求的平均服务时间,单位毫秒: await l/O请求的平均等待时间,单位毫秒;值越小,性能越好: util 一秒中有百分几的时间用于/O操作。接近100%时,表示磁盘带宽跑满,需要优化程序或者增加磁盘; rkB/s、wkB/s根据 系统应用不同会有不同的值,但有规律遵循:长期、超大数据读写,肯定不正常,需要优化程序读取。 svctm的值与await的值很接近,表示几乎没有I/O等待,磁盘性能好, 如果await的值远高于svctm的值,则表示1/O队列等待 太长,需要优化程序或更换更快磁 // 具体信息 pidstat -d 2 -p 5103
4.6 网络IO:ifstat
// 采样频率1S ifstat 1