JVM 下篇
2024-05-18 13:50:26 7 举报
AI智能生成
JVM 下篇
作者其他创作
大纲/内容
第1章 概述篇
1-大厂面试题(见“JVM面试题”)
2-背景说明
1-生产环境中的问题
生产环境发生了内存溢出该如何处理?
生产环境应该给服务器分配多少内存合适?
如何对垃圾回收器的性能进行调优?
生产环境CPU负载飙高该如何处理?
生产环境应该给应用分配多少线程合适?
不加log,如何确定请求是否执行了某一行代码?
不加log,如何实时查看某个方法的入参与返回值?
2-为什么要调优?
防止出现OOM
解决OOM
减少Full GC出现的频率
3-不同阶段的考虑
上线前
项目运行阶段
线上出现OOM
3-调优概述
1-监控的依据
运行日志
异常堆栈
GC日志
线程快照
堆转储快照
2-调优的大方向
合理地编写代码
充分并合理的使用硬件资源
合理地进行JVM调优
4-性能优化的步骤
第1步(发现问题):性能监控
介绍
GC频繁
cpu load过高
OOM
内存泄露
死锁
程序响应时间较长
第2步(排查问题):性能分析
介绍
打印GC日志,通过GCviewer或者 http://gceasy.io 来分析异常信息
灵活运用命令行工具、jstack、jmap、jinfo等
dump出堆文件,使用内存分析工具分析文件
使用阿里Arthas、jconsole、JVisualVM来实时查看JVM状态
jstack查看堆栈信息
第3步(解决问题):性能调优
介绍
适当增加内存,根据业务背景选择垃圾回收器
优化代码,控制内存使用
增加机器,分散节点压力
合理设置线程池线程数量
使用中间件提高程序效率,比如缓存、消息队列等
其他……
5-性能评价/测试指标
1-停顿时间(或响应时间)
2-吞吐量
对单位时间内完成的工作量(请求)的量度
在GC中:运行用户代码的事件占总运行时间的比例(总运行时间:程序的运行时间+内存回收的时间)吞吐量为1-1/(1+n),其中-XX::GCTimeRatio=n
3-并发数
同一时刻,对服务器有实际交互的请求数
例如:1000个人同时在线,估计并发数在5%-15%之间,也就是同时并发量:50-150之间
4-内存占用
Java堆区所占的内存大小
5-相互之间的关系
以高速公路通行状况为例
吞吐量:每天通过高速公路收费站的车辆的数据(也可以理解为收费站收取的高速费)
并发数:高速公路上正在行驶的车辆的数目
响应时间:车速
起初车辆(并发数)比较少,提高车辆高速费能多收一点,车辆数目提高到一定程度再提高的话会导致车速过慢,甚至是拥堵,高速费自然就少了
第2章 JVM监控及诊断工具-命令行篇
01-概述
02-jps:查看正在运行的Java进程
基本情况
类似Linux的ps命令
测试
基本语法
options参数
hostid参数(不建议使用,了解即可)
03-jstat:查看JVM统计信息
基本情况
基本语法
option参数
-gc
EC:Eden区的大小
EU:Eden区已使用的大小
S0C:幸存者0区的大小
S1C:幸存者1区的大小
S0U:幸存者0区已使用的大小
S1U:幸存者1区已使用的大小
MC:元空间的大小
MU:元空间已使用的大小
OC:老年代的大小
OU:老年代已使用的大小
CCSC:压缩类空间的大小
CCSU:压缩类空间已使用的大小
YGC:从应用程序启动到采样时young gc的次数
YGCT:从应用程序启动到采样时young gc消耗时间(秒)
FGC:从应用程序启动到采样时full gc的次数
FGCT:从应用程序启动到采样时的full gc的消耗时间(秒)
GCT:从应用程序启动到采样时gc的总时间
interval参数
用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
count参数
用于指定查询的总次数
-t参数
可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
经验
-h参数
可以在周期性数据输出时,输出多少行数据后输出一个表头信息
补充
测试
-class
-gc
-gccapacity
-gcutil
-gccause
-gcnew
-compiler
-printcompilation
-t
04-jinfo:实时查看和修改JVM配置参数
基本情况
基本语法
查看
jinfo -sysprops PID (可以查看由System.getProperties()的取得的参数(当前进程对应系统的属性信息))
jinfo -flags PID (查看曾经赋值过的一些参数)
jinfo -flag 具体参数 PID (查看某个Java进程的具体参数的值)
修改
针对boolean类型
jinfo -flag [+-]具体参数 PID
针对非boolean类型
jinfo -flag 具体参数=具体参数值 PID
扩展
java -XX:+PrintFlagsInitial (查看所有JVM参数启动的初始值)
java -XX:+PrintFlagsFinal (查看所有JVM参数的最终值)
java -XX:+PrintCommandLineFlags (查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值)
05-jmap:导出内存映像文件&内存使用情况
基本情况
基本语法
测试
使用1:导出内存映像文件
手动的方式
jmap -dump:format=b,file=<filename.hprof> <pid>
jmap -dump:live,format=b,file=<filename.hprof> <pid>
自动的方式
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeampDumpPath=<filename.hprof>
使用2:显示堆内存相关信息
jmap -heap pid
jmap -histo pid
使用3:其它作用
jmap -permstat pid (查看系统的ClassLoader信息)
jmap -finalizerinfo (查看堆积在finalizerinfo 队列中的对象)
小结(主要对手动方式说明)
06- jhat:JDK自带堆分析工具
基本情况
基本语法
07-jstack:打印JVM中线程快照
基本情况
基本语法
测试
(见视频P317)
08-jcmd:多功能命令行
基本上集结了上面所有命令的功能
基本情况
基本语法
主要用 jcmd pid help 命令,查看有哪些参数可以用,再官网看这些参数是干嘛的
09-jstatd:远程主机信息收集
第3章 JVM监控及诊断工具-GUI篇
01-工具概述
02-JConsole
基本概述
启动
三种连接方式
主要作用
(见下图红框部分即代表其可以显示的所有项了)
03-Visual VM
基本概述
插件的安装
连接方式
主要功能
测试
就是前面学的命令集合,比如这里“概述”部分
死锁案例(此处截图已经不是上面那个代码)
04-eclipse MAT
基本概述
获取堆dump文件
dump文件内容
两点说明
获取dump文件
分析堆dump文件
histogram
展示了各个类的实例数目和这些实例的heap或Retainedheap的总和
thread overview
查看系统中的Java线程
查看局部变量的信息
获得对象相互引用的关系
with outgoing references
ArrayList“with outgoing references”情况
with incoming references
数组元素“with incoming references”情况
浅堆与深堆
shallow heap
retained heap
补充:对象实际大小
具体计算公式见:https://blog.csdn.net/shangshanzixu/article/details/114828860?spm=1001.2014.3001.5501
案例
练习
案例分析:StudentTrace
支配树
案例:Tomcat堆溢出分析
说明
分析过程
一般先看占用内存最大的对象,鼠标触碰到饼状图不同部分下面的深堆浅堆就会变化
鼠标左键单击,查看它引用了哪些对象
同理还是分析占用内存最多的对象
分析该对象
继续深入分析,此时查看的是value值,因为只有它是我们可以改变的,其它属性都不是我们所能左右的
之后查看它总数内存占多大(这里有个注意点:最好用OQL查该对象的总数,而不是看Total的值,其代表容器的容量的大小,因为map和数组等等结构都有自动扩容机制,实际对象数目很可能小于容器大小),及占用内存和当前堆内存大小的比例(它是不是占比很高)
查看其信息,创建时间到结束时间非常短,所以怀疑是短时间内创建大量session导致的,查看dump文件里的session数量
对所有session最初创建时间和最晚结束时间进行计算,验证我们的猜想
支持使用OQL语言查询对象信息
补充1:再谈内存泄漏
内存泄漏的理解与分类
Java中内存泄漏的8种情况
1-静态集合类
2-单例模式
3-内部类持有外部类
4-各种连接,如数据库连接、网络连接和IO连接等
5-变量不合理的作用域
6-改变哈希值
案例
案例1
案例2
7-缓存泄漏
案例
注意这里创建字符串要用new的方式创建,确保在堆中有对象指向常量池的字符串常量。因为垃圾回收器只会回收new String("obejct1")所创建的String对象,而不会回收常量池中的字符串常量"obejct1"。常量池中的字符串常量通常在整个程序运行期间都是可用的。所以写成String ref1 = "object1"垃圾回收是不会成功的。
8-监听器和回调
内存泄漏案例分析
案例1
案例代码
分析
解决方法
案例2(移动端开发案例)
案例代码
分析
解决方法
补充2:支持 OQL 语言查询对象信息
SELECT子句
FROM子句
WHERE子句
内置对象与方法
05-JProfiler
基本概述
介绍
特点
主要功能
安装与配置
下载与安装
JProfiler中配置IDEA
IDEA集成JProfiler
下载插件两种方式
方式一
方式二
具体使用
数据采集方式
如何选择:①如果是堆内存泄漏OOM的分析,Sampling模式完全可以完成该工作,就不要用重构模式了 ②如果是正在运行的程序也不要用重构模式
Instrumentation重构模式
Sampling抽样模式
遥感监测 Telemetries
记录对象和数组的数目
内存视图 Live Memory
下面“All Objects”视图可以挖掘的信息/着重关注的信息
许多加了“”双引号的都是属于前面某张截图的内容,建议结合看,不然会有点懵,如“分析”,就是上图里“分析”部分的内容
该功能会急剧降低程序性能,所以只有怀疑有内存泄漏要分析才用,平时就关闭
已经怀疑到某个对象泄漏问题了,则可以继续进行下面的堆内存追踪
堆遍历 heap walker
图表的引用关系确实更加清晰
图中这个保存快照的方法只能存储为html或者csv文件,内容感觉好少不友好,使用ctrl+shift+s或者选择菜单栏“Profiling”->“Save HPROF snapshot”转储快照hprof文件内容很友好,但它的缺点是保存的是当前时刻的快照
cpu视图 cpu views
线程视图 thread
监控和锁 Monitors &Locks
案例分析
案例1(正常情况)
如下每次GC完剩余内存不是增长趋势说明正常
案例2(内存溢出)
这里的内存溢出告诉我们静态集合容易出现问题,慎用!!!
下图可以看到GC是正常有执行,但GC后的剩余内存总体是增加的,查看类的实例个数也是不会降下来的,说明内存溢出
06-Arthas
具体看官网:https://arthas.aliyun.com/doc/commands.html
基本概述
相较于上面工具的优点
安装与使用
相关诊断指令
07-Java Mission Control
历史
启动
概述
功能:实时监控JVM运行时的状态
Java Flight Recorder
08-其它工具
Flame Graphs(火焰图)
使用场景:一般我们是面向接口编程,随着业务的发展,甲方发现接口不稳定,或者性能不好。为了改善接口性能,先要找到性能瓶颈就可以用它
Tprofiler
Btrace
TourKit
JProbe
Spring Insight
自己的总结:无论哪款工具常用的也就是内存方面的功能,如果要分析内存泄漏还需要分析堆方面的内容。其它功能如方法执行慢看CPU方面功能,线程问题(死锁等等)看线程方面功能。如Profiler对应常用的功能
第4章 JVM运行时参数
01-JVM参数选项类型
类型一:标准参数选项
类型二:-X参数选项
类型三:-XX参数选项
02-添加JVM参数选项
jinfo能修改的参数具体见“第2章 JVM监控及诊断工具-命令行篇” -> “04-jinfo:实时查看和修改JVM配置参数” -> “基本语法” -> “修改”
03-常用的JVM参数选项
打印设置的XX选项及值(查)
堆、栈、方法区等内存大小设置
OutOfMemory相关的选项
垃圾收集器相关选项
复习
查看默认垃圾回收器
-XX:+PrintCommandLineFlags 输出
Serial回收器
ParNew回收器
CMS回收器
补充参数
特别说明
G1回收器
Mixed GC调优参数
怎么选择垃圾回收器
GC日志相关选项
常用参数
其它参数
其它参数
第二三个命令是针对代码缓存大小,即JIT会将代码缓存起来的大小,如果这个缓存满了,就只能走解释器,解释器执行速度较慢
面试题:什么是TLAB,TLAB有什么用。最后一个设置TLAB大小,其是为了解决多个线程访问堆空间的问题,如果多个线程访问Edge区为了保证安全性需要加锁,加锁效率就低了,所以在Edge区为每个线程分配一份TLAB,届时每个线程用自己的TLAB访问堆空间就能解决安全问题,还能提高效率/吞吐量
04-通过Java代码获取JVM参数
第5章 分析GC日志
01-GC日志参数
02-GC日志格式
复习:GC分类
需要区分Full GC和Major GC
日志文件能够很好体现用的什么GC
GC日志分类
MinorGC
FullGC
GC日志结构剖析
垃圾收集器
GC前后情况
GC时间
MinorGC日志解析
案例
解析
FullGC日志解析
案例
解析
03-GC日志复习工具
GCeasy
基本概述
GCViewer
基本概述
安装
其他工具
GChisto
官网上没有下载的地方,需要自己从SVN上拉下来编译
不过这个工具似乎没怎么维护了,存在不少bug
HPjmeter
工具很强大,但只能打开由以下参数生成的GC log,-verbose:gc -Xloggc:gc.log。添加其它参数生成的gc.log无法打开
HPjmeter集成了以前的HPjtune功能,可以复习在HP机器上产生的垃圾回收日志文件
第6章 OOM常见各种场景及解决方案
案例1:堆溢出
案例2:元空间溢出
案例3:GC overhead limit exceeded
案例4:线程溢出
第7章 性能优化案例
1-概述篇
2-调优基本问题
2-OOM案例
面试题
OOM案例1:堆溢出
OOM案例2:元空间溢出
如果是远程查看只能用命令jstat判断了
OOM案例3:GC overhead limit exceeded
OOM案例4:线程溢出
性能优化工具Jmeter
案例1:调整堆大小提高服务的吞吐量
案例2:调整垃圾回收器提高服务的吞吐量
案例3: JVM优化之JT优化
案例4: G1并发执行的线程数对性能的影响
案例5:合理配置堆内存
特殊问题:新生代与老年代的比例
案例6: CPU占用很高排查方案
日均百万级订单交易系统如何设置JVM参数
注意
1.prof文件不会覆盖,即会保留之前的文件,而log文件会进行覆盖操作。
2.prof(dump)文件会随着程序运行越来越大,我们可以定期清理再生成新的prof文件。log文件可以修改为追加写入(覆盖写不好),也是定期清理比较好
0 条评论
下一页