JVM解剖
榜样的力量是用来超越的,生死看淡,不服就干
常见的垃圾回收算法
引用计数
复制
标记清除
标记整理
如何确定垃圾:
内存中已经不再使用到的空间就是垃圾, 使用计数器,很难解决相互引用的问题
GC Roots对象作为起点可达性分析,引用可达对象
哪些可以做为GC roots的对象
虚拟机栈中引用的对象
方法区中的类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI(native方法)引用的对象
查看java进行信息(布尔类型:公式-xx:+或者-某个属性值,kv类型值,jinfo查询运行程序配置):
jinfo -flag PrintGCDetails 39742
jinfo -flag +PrintGCDetails 39742 开启打印
-XX:+PrintGCDetails +是开启
jinfo -flag MetaspaceSize 39742
jinfo -flag MaxTenuringThreshold 39742 晋升到老年区的匝值
jinfo -flags 39742 所有相关配置信息 默认堆内存是计算机内存的4分之一
-Xms 等价于-xx:InitalHeapSize
-Xmx 等价于-xx:MaxHeapSize
java -XX:+PrintFlagsInitial 查看初始值全部参数
java -XX:+PrintFlagsFinal -version 打印的参数中有 := 表示修改知乎的更新参数值 , =是初始值未修改过 看下修改更新
java -XX:+PrintFlagsFinal -version -XX:MataspaceSize = 512M T (T表示运行的类名)
java -XX:+PrintCommandLineFlags -version 查看默认垃圾回收器 UseParallelGC,并行gc
➜ ~ jinfo -flag ThreadStackSize 41664
-XX:ThreadStackSize=1024
-Xms
初始大小内存,默认为物理内存的1/64,等价于-xx:InitalHeapSize
-Xmx
最大分配内存,默认为物理内存的1/4,-xx:MaxHeapSize
-Xss
设置单个线程栈的大小,一般默认为512k-1024k,等价于-xx:ThreadStackSize
-Xmn
设置年轻代的大小
-XX:MetaspaceSize: 元空间并不在虚拟机中,而是使用本地内存
jinfo -flag MetaspaceSize 41664 -XX:MetaspaceSize=21807104 默认使用21M
输出GC详细信息
名称 GC前内存,GC后内存多少,总的Young GC
-XX:SurvivorRatio 新生代中eden和S0/S1空间的比例, 默认Eden:S0:S1 = 8:1:1 8倍
-XX:NewRatio 配置年轻代和老年代的占比
-XX:MaxTenuringTreshold 进入老年代的匝值最大是15
[PSYoungGen: 1972K->504K(2560K)] 1972K->740K(9728K), 0.0156109 secs]
https://www.javatang.com/archives/2017/10/25/36441958.html
强引用:无法被垃圾回收
软引用:当内存不足才能被回收
弱引用:垃圾回收器执行的时候,如果发现是弱引用就会被回收
虚引用:形同虚设,执行前和执行后是null,当垃圾回收器器,执行的时候,会把虚引用的对象,放入引用队列中,随时可以回收
oom
linux系统默认允许单个进程可以创建的线程是1024个
垃圾回收方式
串行回收(serial):只使用一个线程进行回收,会暂停其他线程操作,stop world
并行回收(Parallel):多个垃圾收集器并行工作,其他操作也会暂停,stop world
并发回收(CMS):用户线程和垃圾收集器同时执行,不需要暂停,还是会产生垃圾碎片
G1回收:不会产生很多内存碎片,stop the world可控,在停顿时间上添加预测机制,用户可以指定期望停顿时间,停顿时间低,改变Eden,Survivor,old 划分独立的小区域,逻辑上的分代隔离,物理上没有区分,增加了大型区域 Humongous,大于G1中region大小50%的对象会存放
JVM初始参数:
java -XX:+PrintCommandLineFlags -version
-XX:+UserSerialGC
jinfo -flag UserSerialGC 6735
7个垃圾收集器 ( 划区使用 ):
Young Gen: Serial Coping, Paralllel Scavenge, ParNew
Old Gen: Serial MSC, Parallel Compacting, CMS
G1收集器不做区域划分
参数说明:
DefNew: Default New Generation ...
-XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC java version "1.8.0_151" Java(TM) SE Runtime Environment (build 1.8.0_151-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
G1:
标记过程:
初始标记,并发标记,最终标记,筛选标记
JVMGC + SpringBoot微服务的生产部署和调参优化
java -server -Xms1024m -Xmx1024m --XX:UseG1GC -jar xx.war
Undertow
生产环境服务器变慢,诊断思路和性能调优,定位?
整机
top 查看cpu和内存 loadaverage 负载压力值 1分钟 15分钟, 查看cpu
uptime 系统性能精简版
cpu:
vmstat -n 2 3 通过两个数字参数来完成,第一个参数是采样的时间间隔数单位是秒,第二个参数是采样的次数
procs
r:运行和等待cpu时间片的进程数,原则上1和的cpu的运行队列不要超过2,整个系统的运行队列不能超过总核数的2倍,否则代表系统压力过大
b:等待资源的进程数,比如正在等待磁盘I/O、网络I/O等
cpu:
us:用户进程消耗cpu新能占比
sy:内核进程消耗cpu的占比
mpstat -P All 2 查看cpu所有核数
idle cpu空闲率
pidstat -u l -p xx 进程占用cpu的使用率
内存:
free -m 内存占用超过70%则需要扩容
pidstat -p 进程号 -r 采样间隔秒数 内存采用频率
硬盘
df -h 查看磁盘剩余空间数
磁盘IO
iostat -xdk 2 3 await值越小性能越好
pidstat -d 采样间隔秒数 -p 进程号
网络IO
ifstat 1 每秒一次采样
cpu占用过高排查?
1.使用top找出进程号
2.ps -ef | grep java | grep -v grep, jps -l
3.定位代码和线程
ps -mp 进程id -o THREAD,tid,time
4.将需要的线程ID转换为16进制格式小写
printf "%x\n" 有问题的线程id
5.jstack 进程id | grep tid(16进制线程的小写)