史上最全JVM知识点梳理
2021-06-03 17:37:00 0 举报
AI智能生成
整理的康师傅老师的JVM课程笔记,希望能帮助您~
作者其他创作
大纲/内容
https://docs.oracle.com/javase/8/
https://www.processon.com/view/link/606d1f9d7d9c0829db732d26#map
01_内存与垃圾回收篇
01_JVM与Java体系结构
02_类加载子系统
03_运行时数据区概述及线程
04_程序计数器
05_虚拟机栈
06_本地方法接口
07_本地方法栈
08_堆
09_方法区
10_对象的实例化内存布局与访问定位
11_直接内存
12_执行引擎
13_StringTable
14_垃圾回收概述
15_垃圾回收相关算法
16_垃圾回收相关概念
17_垃圾回收器
怎么选择垃圾回收器?
优化调整堆的大小让JVM自适应完成
如果内存小于100M,使用串行收集器
如果是单核、单机程序,并且没有停顿时间的要求,使用串行收集器
如果是多CPU、需要高吞吐量、允许停顿时间超过1秒,选择并行或者JVM自己选择
如果是多CPU、追求低停顿时间,需快速响应(比如延迟不能超过1秒,如互联网应用),使用并发收集器,官方推荐G1,性能高。现在互联网的项目,基本都是使用G1。
最后需要明确一个观点:
没有最好的收集器,更没有万能的收集器
调优永远是针对特定场景、特定需求,不存在一劳永逸的收集器
GC日志分析
-verbose:gc
这个只会显示总的GC堆的变化
参数解析
GC、Full GC:GC的类型,GC只在新生代上进行,Full GC包括新生代、老年代、永久代
Allocation Failure:GC发生的原因
80832k->19298k:堆在GC前的大小和GC后的大小
227840k:现在堆的大小
0.0084018 secs:GC持续的时间
-verbose:gc -XX:+PrintGCDetails
输入信息
参数解析
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
带上了日期和时间
日志补充说明
年轻代 GC
老年代 GC
GC日志分析工具
02_字节码与类的加载篇
Class文件结构
01_概述
字节码文件的跨平台性
Java的前端编译器
透过字节码指令看代码细节
02_虚拟机的基石:Class文件
操作码 (操作数)
方式一
方式三
03_Class文件结构
01-魔数:Class文件的标志
02-Class文件版本号
03-常量池:存放所有常量
1-常量池计数器
2-常量池表
2.1 字面量和符号引用
2.2 常量类型和结构
04-访问标识
05-类索引、父类索引、接口索引集合
06-字段表集合
1-字段计数器
2-字段表
07-方法表集合
1-方法计数器
2-方法表
08-属性表集合
1-属性计数器
2-属性表
小结
04_使用javap指令解析Class文件
1-解析字节码的作用
2- javac -g操作
3- javap的用法
4-使用举例
5-总结
字节码指令集与解析举例
01-概述
执行模型
字节码与数据类型
指令分类
02-加载与存储指令
复习:再谈操作数栈与局部变量表
操作数栈
局部变量表
1-局部变量压栈指令
2-常量入栈指令
指令push系列
指令ldc系列
指令const系列
3-出栈装入局部变量表指令
03-算术指令
所有算术指令
比较指令的说明
04-类型转换指令
1-宽化类型转换
2-窄化类型转换
05-对象的创建与访问指令
1-创建指令
2-字段访问指令
3-数组操作指令
4-类型检查指令
06-方法调用与返回指令
1-方法调用指令
2-方法返回指令
07-操作数栈管理指令
08-控制转移指令
1-条件跳转指令
2-比较条件跳转指令
3-多条件分支指令
4-无条件跳转
09-异常处理指令
1-抛出异常指令
2-异常处理与异常表
10-同步控制指令
1-方法级的同步
2-方法内指定指令序列的同步
类的加载过程(类的生命周期)详解
01-概述
类的使用过程
大厂面试题
02-过程一:Loading(加载)阶段
1-加载完成的操作
2-二进制流的获取方式
3-类模型与Class实例的位置
4-数组类的加载
03-过程二:Linking(链接)阶段
1-环节1:链接阶段之Verification(验证)
2-环节2:链接阶段之Preparation(准备)
3-环节3:链接阶段之Resolution(解析)
04-过程三:Initialization(初始化)阶段
1-static与final的搭配问题
2-<clinit>()的线程安全性
3-类的初始化情况:主动使用vs被动使用
-XX:+TraceClassLoading
05-过程四:类的Using(使用)
06-过程五:类的Unloading(卸载)
回顾:方法区的垃圾回收
再谈类的加载器
01-概述
1-大厂面试题
2-类加载的分类
3-类加载器的必要性
4-命名空间
5-类加载机制的基本特征
02-复习:类的加载器分类
1-引导类加载器
2-扩展类加载器
3-系统类加载器
4-用户自定义类加载器
03-测试不同的类加载器
04-ClassLoader源码解析
ClassLoader的主要方法
SecureClassLoader与URLClassLoader
ExtClassLoader与AppClassLoader
Class.forName()与ClassLoader.loadClass()
05-双亲委派模型
定义与本质
优势与劣势
破坏双亲委派机制
破坏双亲委派机制1
破坏双亲委派机制2
破坏双亲委派机制3
热替换的实现
06-沙箱安全机制
JDK1.0时期
JDK1.1时期
JDK1.2时期
JDK1.6时期
07-自定义类的加载器
实现方式
08-Java9新特性
双亲委派模型改变
03_性能监控与调优篇
概述篇
1-大厂面试题
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-停顿时间(或响应时间)
-XX:MaxGCPauseMillis
2-吞吐量
对单位时间内完成的工作量(请求)的量度
在GC中:运行用户代码的时间占总运行时间的比例(总运行时间:程序的运行时间 + 内存回收的时间)
吞吐量为 1 - 1/(1+n)。-XX:GCTimeRatio=n
吞吐量为 1 - 1/(1+n)。-XX:GCTimeRatio=n
3-并发数
同一时刻,对服务器有实际交互的请求数
4-内存占用
Java堆区所占的内存大小
5-相互间的关系
以高速公路通行状况为例
JVM监控及诊断工具-命令行篇
01-概述
简单命令行工具
02-jps:查看正在运行的Java进程
基本情况
测试
基本语法
options参数
hostid参数
03-jstat:查看JVM统计信息
基本情况
基本语法
option参数
-gc
新生代相关
S0C是第一个幸存者区的大小(字节)
S1C是第二个幸存者区的大小(字节)
S0U是第一个幸存者区已使用的大小(字节)
S1U是第二个幸存者区已使用的大小(字节)
EC是Eden空间的大小(字节)
EU是Eden空间已使用的大小(字节)
老年代相关
OC是老年代的大小(字节)
OU是老年代已使用的大小(字节)
方法区(元空间)相关
MC是方法区的大小
MU是方法区已使用的大小
CCSC是压缩类空间的大小
CCSU是压缩类空间已使用的大小
其它
YGC是指从应用程序启动到采样时young gc次数
YGCT是指从应用程序启动到采样时young gc消耗的时间(秒)
FGC是指从应用程序启动到采样时full gc次数
FGCT是指从应用程序启动到采样时full gc消耗的时间(秒)
GCT是指从应用程序启动到采样时gc的总时间
interval参数
用于指定输出统计数据的周期,单位为毫秒。即查询间隔
count参数
用于指定查询的总次数
-t参数
可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
经验
-h参数
可以在周期性数据输出时,输出多少行数
补充
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:导出内存映射文件&内存使用情况
基本情况
基本语法
-dump
生成Java堆转储快照:dump文件
特别的:-dump:live只保存堆中的存活对象
-heap
输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用
-histo
输出堆中对象的统计信息,包括类、实例数量和合计容量
特别的:-histo:live只统计堆中的存活对象
-permstat
以ClassLoader为统计口径输出永久代的内存状态信息
仅linux/solaris平台有效
-finalizerinfo
显示在F-Queue中等待Finalizer线程执行finalize方法的对象
仅linux/solaris平台有效
-F
当虚拟机进程对-dump选项没有任何响应时,可使用此选项强制执行生成
仅linux/solaris平台有效
-h | -help
jmap工具使用的帮助命令
-J <flag>
传递参数给jmap启动的jvm
使用1:导出内存映像文件
手动的方式
jmap -dump:format=b,file=<filename.hprof> <pid>
jmap -dump:live,format=b,file=<filename.hprof> <pid>
自动的方式
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=<filename.hprof>
使用2:显示堆内存相关信息
jmap -heap pid
jmap -histo
使用3:其它作用
jmap -permstat pid
查看系统的ClassLoader信息
jmap -finalizerinfo
查看堆积在finalizer队列中的对象
小结
06-jhat:JDK自带堆分析工具
基本情况
基本语法
option参数:-stack false|true
关闭|打开对象分配调用栈跟踪
option参数:-refs false|true
关闭|打开对象应用跟踪
option参数:-port port-number
设置jhat HTTP Server的端口号,默认7000
option参数:-exclude exclude-file
执行对象查询时需要排除的数据成员
option参数:-baseline exclude-file
指定一个基准堆转储
option参数:-debug int
设置debug级别
option参数:-version
启动后显示版本信息就退出
option参数:-J<flag>
传入启动参数,比如-J -Xmx512m
07-jstack:打印JVM中线程快照
基本情况
基本语法
option参数:-F
当正常输出的请求不被响应时,强制输出线程堆栈
option参数:-l
除堆栈外,显示关于所的附加信息
option参数:-m
如果调用到本地方法的话,可以显示C/C++的堆栈
option参数:-h
帮助操作
08-jcmd:多功能命令行
基本使用
基本语法
jcmd -l
列出所有的JVM进程
jcmd pid help
针对指定的进程,列出支持的所有命令
jcmd pid 具体命令
显示指定进程的指令命令的数据
09-jstatd:远程主机信息收集
JVM监控及诊断工具-GUI篇
01-工具概述
02-jConsole
基本概念
启动
jdk/bin目录下,启动jconsole.exe命令即可
不需要使用jps命令来查询
三种连接方式
Local
使用JConsole连接一个正在本地系统运行的JVM,并且执行程序的和运行JConsole的需要是同一个用户。
JConsole使用文件系统的授权通过RMI连接器连接到平台的MBean服务器上。这种从本地连接的监控能力只有Sun的JDK具有。
JConsole使用文件系统的授权通过RMI连接器连接到平台的MBean服务器上。这种从本地连接的监控能力只有Sun的JDK具有。
Remote
使用下面的URL通过RMI连接器连接到一个JMX代理,service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi。
JConsole为建立连接,需要在环境变量中设置mx.remote.credentials来指定用户名和密码,从而进行授权。
JConsole为建立连接,需要在环境变量中设置mx.remote.credentials来指定用户名和密码,从而进行授权。
Advanced
使用一个特殊的URL连接JMX代理。一般情况使用自己定制的连接器而不是RMI提供的连接器来连接JMX代理,或者是一个使用JDK1.4的实现了JMX和JMX Remote的应用。
主要作用
03-Visual VM
基本概念
插件的安装
连接方式
本地连接
监控本地Java进程的CPU、类、线程等
远程连接
1-确定远程服务器的IP地址
2-添加JMX(通过JMX技术具体监控远端服务器哪个Java进程)
3-修改bin/catalina.sh文件,远程连接的Tomcat
4-在.../conf中添加jmxremote.access和jmxremote.password文件
5-将服务器地址改为公网IP地址
6-设置阿里云安全策略和防火墙策略
7-启动Tomcat,查看Tomcat启动日志和端口监听
8-JMX中输入端口号、用户名、密码登录
主要功能
1-生成/读取堆内存快照
2-查看JVM参数和系统属性
3-查看运行中的虚拟机进程
4-生成/读取线程快照
5-程序资源的实时监控
6-其他功能
JMX代理连接
远程环境监控
CPU分析和内存分析
04-eclipse MAT
基本概述
获取堆dump文件
dump文件内容
两点说明
获取dump文件
分析堆dump文件
histogram
展示了各个类的实例数目以及这些实例的Shallow heap或 Retainedheap的总和
thread overview
查看系统中的Java线程
查看局部变量的信息
获得对象相互引用的关系
with outgoing references
with incoming references
浅堆与深堆
shallow heap
retained heap
补充:对象实际大小
练习
图一
图二
案例分析:StudentTrace
支配树
案例:Tomcat堆溢出分析
说明
分析过程
图1
图2
图3
图4
图5
图6
图7
图8
补充1:再谈内存泄漏
内存泄漏的理解与分类
内存泄漏
Java中内存泄漏的8种情况
1-静态集合类
2-单例模式
3-内部类持有外部类
4-各种连接,如数据库连接、网络连接和IO连接等
5-变量不合理的作用域
6-改变哈希值
7-缓存泄漏
8-监听器和回调
内存泄漏案例分析
案例
案例代码
分析
图一
图二
解决办法
补充2:支持使用OQL语言查询对象信息
SELECT子句
FROM子句
WHERE子句
内置对象与方法
05-JProfiler
基本概述
介绍
特点
主要功能
1-方法调用
对方法调用的分析可以帮助您了解应用程序正在做什么,并找到提高其性能的方法
2-内存分配
通过分析堆上对象、引用链和垃圾收集能帮您修复内存泄漏问题,优化内存使用
3-线程和锁
JProfiler提供多种针对线程和锁的分析视图助您发现多线程问题
4-高级子系统
许多性能问题都发生在更高的语义级别上。例如,对于JDBC调用,您可能希望找出执行最慢的SQL语句。JProfiler支持对这些子系统进行集成分析
安装与配置
下载与安装
JProfiler中配置IDEA
IDEA集成JProfiler
具体使用
数据采集方式
Instrumentation重构模式
Sampling抽样模式
遥感监测 Telemetries
内存视图 Live Memory
堆遍历 heap walker
cpu视图 cpu views
线程视图 threads
监视器&锁 Monitors&locks
案例分析
案例1
06-Arthas
基本概述
背景
概述
基于哪些工具开发而来
官方使用文档
https://arthas.aliyun.com/zh-cn/
安装与使用
安装
工程目录
启动
查看进程
查看日志
cat ~/logs/arthas/arthas.log
参看帮助
java -jar arthas-boot.jar -h
web console
退出
相关诊断指令
基础指令
jvm相关
dashboard
thread
jvm
其它
class/classloader相关
sc
sm
jad
mc、redefine
classloader
monitor/watch/trace相关
monitor
watch
trace
stack
tt
其它
profiler/火焰图
options
07-Java Mission Control
历史
启动
概述
功能:实时监控JVM运行时的状态
Java Flight Recorder
08-其它工具
Flame Graphs(火焰图)
Tprofiler
Btrace
YourKit
JProbe
Spring Insight
JVM运行时参数
01-JVM参数选项类型
类型一:标准参数选项
特点
比较稳定,后续版本基本不会变化
以-开头
各种选项
运行java或者java -help可以看到所有的标准选项
补充内容:-server与-client
类型二:-X参数选项
特点
非标准化参数
功能还是比较稳定的。但官方说后续版本可能会变更
以-X开头
各种选项
运行java -X命令可以看到所有的X选项
JVM的JIT编译模式相关的选项
-Xint
禁用JIT,所有字节码都被解释执行,这个模式的速度最慢的
-Xcomp
所有字节码第一次使用就都被编译成本地代码,然后再执行
-Xmixed
混合模式,默认模式,让JIT根据程序运行的情况,有选择地将某些代码编译进行缓存起来
特别地
-Xmx -Xms -Xss属于 XX 参数?
-Xms<size>
设置初始Java堆大小,等价于-XX:InitialHeapSize
-Xmx<size>
设置最大Java堆大小,等价于-XX:MaxHeapSize
-Xss<size>
设置Java线程堆栈大小,-XX:ThreadStackSize
类型三:-XX参数选项
特点
非标准化参数
使用的最多的参数类型
这类选项属于实验性,不稳定
以-XX开头
作用
用于开发和调试JVM
分类
Boolean类型格式
-XX:+<option>表示启用option属性
-XX:-<option>表示禁用option属性
举例
说明:因为有的指令默认是开启的,所以可以使用-关闭
非Boolean类型格式(key-value类型)
子类型1:数值型格式-XX:<option>=<number>
子类型2:非数值型格式-XX:<name>=<string>
特别地
-XX:+PrintFlagsFinal
输出所有参数的名称和默认值
默认不包括Diagnostic和Experimental的参数
可以配合-XX:+UnlockDiagnosticVMOptions和-XX:UnlockExperimentalVMOptions使用
02-添加JVM参数选项
Eclipse
IDEA
运行jar包
java -Xms50m -Xmx50m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -jar demo.jar
通过Tomcat运行war包
Linux系统下可以在tomcat/bin/catalina.sh中添加类似如下配置:
JAVA_OPTS="-Xms512M -Xmx1024M"
JAVA_OPTS="-Xms512M -Xmx1024M"
Windows系统下在catalina.bat中添加类似如下配置:
set "JAVA_OPTS=-Xms512M -Xmx1024M"
set "JAVA_OPTS=-Xms512M -Xmx1024M"
程序运行过程中
使用jinfo -flag <name>=<value> <pid> 设置非Boolean类型参数
使用jinfo -flag [+|-]<name> <pid> 设置Boolean类型参数
03-常用的JVM参数选项
打印设置的XX选项及值
-XX:+PrintCommandLineFlags
可以让程序运行前打印出用户手动设置或者JVM自动设置的XX选项
-XX:+PrintFlagsInitial
表示打印出所有XX选项的默认值
-XX:+PrintFlagsFinal
表示打印出XX选项在运行程序时生效的值
-XX:+PrintVMOptions
打印JVM的参数
堆、栈、方法区等内存大小设置
栈
-Xss128k
设置每个线程的栈大小为128k
等价于 -XX:ThreadStackSize=128k
堆内存
-Xms3550m
等价于-XX:InitialHeapSize,设置JVM初始堆内存为3550M
-Xmx3550m
等价于-XX:MaxHeapSize,设置JVM最大堆内存为3550M
-Xmn2g
设置年轻代大小为2G
官方推荐配置为整个堆大小的3/8
-XX:NewSize=1024m
设置年轻代初始值为1024M
-XX:MaxNewSize=1024m
设置年轻代最大值为1024M
-XX:SurvivorRatio=8
设置年轻代中Eden区与Survivor区的比值,默认为8
-XX:UseAdaptiveSizePolicy
自动选择各区大小比例
-XX:NewRatio=2
设置老年代与年轻代(包括1个Eden和2个Survivor区)的比值
-XX:PretenureSizeThreadshold=1024
设置让大于此阈值的对象直接分配在老年代,单位为字节
只对Serial、ParNew收集器有效
-XX:MaxTenuringThreshold=15
默认值15
新生代每次MinorGC后,还存活的对象年龄+1,当对象的年龄大于设置的这个值时就进入老年代
-XX:+PrintTenuringDistribution
让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布
-XX:TargetSurvivorRatio
表示MinorGC结束后Survivor区域中占用空间的期望比例
方法区
永久代
-XX:PermSize=256m
设置永久代初始值为256M
-XX:MaxPermSize=256m
设置永久代最大值为256M
元空间
-XX:MetaspaceSize
初始空间大小
-XX:MaxMetaspaceSize
最大空间,默认没有限制
-XX:+UseCompressedOops
压缩对象指针
-XX:+UseCompressedClassPointers
压缩类指针
-XX:CompressedClassSpaceSize
设置Klass Metaspace的大小,默认1G
直接内存
-XX:MaxDirectMemorySize
指定DirectMemory容量,若未指定,则默认与Java堆最大值一样
OutOfMemory相关的选项
-XX:+HeapDumpOnOutOfMemoryError
表示在内存出现OOM的时候,把Heap转存(Dump)到文件以便后续分析
-XX:+HeapDumpBeforeFullGC
表示在出现FullGC之前,生成Heap转储文件
-XX:HeapDumpPath=<path>
指定heap转存文件的存储路径
-XX:OnOutOfMemoryError
指定一个可行性程序或者脚本的路径,当发生OOM的时候,去执行这个脚本
垃圾收集器相关选项
7款经典收集器与垃圾分代之间的关系
垃圾收集器的组合关系
查看默认垃圾回收器
Serial回收器
ParNew回收器
Paraller回收器
CMS回收器
补充参数
特别说明
G1回收器
Mixed GC调优参数
怎么选择垃圾回收器
GC日志相关选项
常用参数
-verbose:gc
输出gc日志信息,默认输出到标准输出
可以独立使用
-XX:+PrintGC
等同于-verbose:gc
表示打开简化的GC日志
表示打开简化的GC日志
可以独立使用
-XX:+PrintGCDetails
在发生垃圾回收时打印内存回收详细的日志,
并在进程退出时输出当前内存各区域分配情况
并在进程退出时输出当前内存各区域分配情况
可以独立使用
-XX:+PrintGCTimeStamps
输出GC发生时的时间戳
不可以独立使用,需要配合-XX:+PrintGCDetails使用
-XX:+PrintGCDateStamps
输出GC发生时的时间戳(以日期的形式,如2013-05-04T21:53:59.234+0800)
不可以独立使用,需要配合-XX:+PrintGCDetails使用
-XX:+PrintHeapAtGC
每一次GC前和GC后,都打印堆信息
可以独立使用
-Xloggc:<file>
把GC日志写入到一个文件中去,而不是打印到标准输出中
其他参数
-XX:+TraceClassLoading
监控类的加载
-XX:+PrintGCApplicationStoppedTime
打印GC时线程的停顿时间
-XX:+PrintGCApplicationConcurrentTime
垃圾收集之前打印出应用未中断的执行时间
-XX:+PrintReferenceGC
记录回收了多少种不同引用类型的引用
-XX:+PrintTenuringDistribution
让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布
-XX:+UseGCLogFileRotaion
启动GC日志文件的自动存储
-XX:+NumberOfGClogFiles=1
GC日志文件的循环数目
-XX:+GCLogFileSize=1M
控制GC日志文件的大小
其他参数
-XX:+DisableExplicitGC
禁止hotspot执行System.gc(),默认禁用
-XX:ReservedCodeCacheSize=<n>[g|m|k]、-XX:InitialCodeCacheSize=<n>[g|m|k]
指定代码缓存的大小
-XX:+UseCodeCacheFlushing
使用该参数让jvm放弃一些被编译的代码,
避免代码缓存被占满时JVM切换到interpreted-only的情况
避免代码缓存被占满时JVM切换到interpreted-only的情况
-XX:+DoEscapeAnalysis
开启逃逸分析
-XX:+UseBiasedLocking
开启偏向锁
-XX:+UseTLAB
使用TLAB,默认打开
-XX:+PrintTLAB
打印TLAB的使用情况
-XX:TLABSize
设置TLAB大小
04-通过Java代码获取JVM参数
上篇上通过Runtime获取
分析GC日志
01-GC日志参数
-verbose:gc
输出gc日志信息,默认输出到标准输出
-XX:+PrintGC
等同于-verbose:gc
表示打开简化的GC日志
表示打开简化的GC日志
-XX:+PrintGCDetails
在发生垃圾回收时打印内存回收详细的日志,
并在进程退出时输出当前内存各区域分配情况
并在进程退出时输出当前内存各区域分配情况
-XX:+PrintGCTimeStamps
输出GC发生时的时间戳
-XX:+PrintGCDateStamps
输出GC发生时的时间戳(以日期的形式,如2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC
每一次GC前和GC后,都打印堆信息
-Xloggc:<file>
把GC日志写入到一个文件中去,而不是打印到标准输出中
02-GC日志格式
复习:GC分类
GC日志分类
MinorGC
FullGC
GC日志结构剖析
垃圾收集器
GC前后情况
GC时间
Minor GC 日志解析
2020-11-20T17:19:43.265-0800
日志打印事件 日期格式 如2013-05-04T21:53:59.234+0800
0.822
gc发生时,Java虚拟机启动以来经过的秒数
[GC (Allocation Failure)
发生了一次垃圾回收,这是一次Minor GC。它不区分新生代GC还是老年代GC,
括号里的内容是gc发生的原因,这里的Allocation Failure的原因是新生代中没有足够区域能存放需要分配的数据而失败。
括号里的内容是gc发生的原因,这里的Allocation Failure的原因是新生代中没有足够区域能存放需要分配的数据而失败。
[PSYoungGen:76800K->8433K(89600K)]
PSYoungGen:表示GC发生的区域,区域名称与使用的GC收集器是密切相关的
Serial收集器:Default New Generation显示DefNew
ParNew收集器:ParNew
Parallel Scanvenge收集器:PSYoung
老年代和新生代同理,也是和收集器名称相关
76800K->8433K(89600K):GC
前该内存区域已使用容量-> GC
后该区域容量(该区域总容量)
前该内存区域已使用容量-> GC
后该区域容量(该区域总容量)
如果是新生代,总容量则会显示整个新生代内存的9/10,即Eden + from/to区
如果是老年代总容量则是全部内存大小,无变化
76800K->8449K(294400K)
在显示完区域容量GC的情况之后,会接着显示整个堆内存区域的GC情况:GC前堆内存已使用容量 -> GC堆内存容量(堆内存总容量)
堆内存总容量 = 9/10 新生代 + 老年代 < 初始化的内存大小
堆内存总容量 = 9/10 新生代 + 老年代 < 初始化的内存大小
, 0.0088371 secs]
整个GC所花费的时间,单位是秒
[Times:user=0.02 sys=0.01, real=0.01 secs]
user:指的是CPU工作在用户态所花费的时间
sys:指的是CPU工作在内核态所花费的时间
real:指的是在此次GC事件中所花费的总时间
Full GC 日志剖析
2020-11-20T17:19:43.794-0800
日志打印时间 日期格式 如2013-05-04T21:53:59.234+0800
1.351
gc发生时,Java虚拟机启动以来经过的秒数
Full GC (Metadata GC Threshold)
发生了一次垃圾回收,这是一次FULL GC。它不区分新生代GC还是老年代GC
括号里的内容是gc发生的原因,这里的Metadata GC Threshold的原因是Metaspace区不够用了。
Full GC(Ergonomics):JVM自适应调整导致的GC
Full GC(System):调用了System.gc()方法
[PSYoungGen: 10082k->0k(89600k)]
PSYoungGen:表示GC发生的区域,区域名称与使用的GC收集器是密切相关的
Serial收集器:Default New Generation显示DefNew
ParNew收集器:ParNew
Parallel Scanvenge收集器:PSYoung
老年代和新生代同理,也是和收集器名称相关
10082k->0k(89600k):GC前该内存区域已使用容量 -> GC后该区域容量(该区域总容量)
如果是新生代,总容量则会显示整个新生代内存的9/10,即Eden + from/to区
如果是老年代总容量则是全部内存大小,无变化
[ParOldGen: 32k->9638k(204800k)]
老年代区域没有发生GC,因为本次GC是metaspace引起的
10114k->9638k(294400k)
在显示完区域容量GC的情况之后,会接着显示整个堆内存区域的GC情况:
GC前堆内存已使用容量 -> GC堆内存容量(堆内存总容量)
堆内存总容量 = 9/10新生代 + 老年代 < 初始化的内存大小
GC前堆内存已使用容量 -> GC堆内存容量(堆内存总容量)
堆内存总容量 = 9/10新生代 + 老年代 < 初始化的内存大小
[Metaspace: 20158k->20156k(1067008k)]
metaspace GC 回收2k空间
0.0285388 secs
整个GC所花费的时间,单位是秒
[Times: user=0.11, sys=0.00, real=0.03 secs]
user:指的是CPU工作在用户态所花费的时间
sys:指的是CPU工作在内核态所花费的时间
real:指的是在此次GC事件中所花费的总时间
03-GC日志分析工具
GCeasy
基本概述
GCViewer
基本概述
安装
其他工具
GChisto
官网上没有下载的地方,需要自己从SVN上拉下来来编译
不过这个工具似乎没怎么维护了,存在不少bug
HPjmeter
工具很强大,但只能打开由以下参数生成的GC log,-verbose:gc
-Xloggc:gc.log。添加其他参数生成的gc.log无法打开
-Xloggc:gc.log。添加其他参数生成的gc.log无法打开
HPjmeter集成了以前的HPjtune功能,可以分析在HP机器上产生的垃圾回收日志文件
OOM常见各种场景及解决方案
面试题
案例1:堆溢出
报错信息
java.lang.OutOfMemoryError:Java heap space
案例模拟
发送请求
http://localhost:8080/add
JVM参数配置
运行结果
原因及解决方案
dump文件分析
jvisualvm分析
MAT分析
gc日志文件
案例2:元空间溢出
元空间存储数据类型
报错信息
java.lang.OutOfMemoryError:Metaspace
案例模拟
示例代码
发送请求
http://localhost:8080/metaSpaceOom
运行结果
JVM参数配置
原因及解决方案
分析及解决
查看监控
查看GC状态
查看GC日志
分析dump文件
jvisualvm分析
MAT分析
解决方案
案例3:GC overhead limit exceeded
案例模拟
示例代码1
JVM配置
报错信息
示例代码2
JVM配置
代码解析
分析及解决
第1步:定位问题代码块
jvisualvm分析
MAT分析
第2步:分析dump文件直方图
第3步:代码修改
案例4:线程溢出
报错信息
java.lang.OutOfMemoryError: unable to create new native Thread
问题原因
出现这种异常,基本上都是创建了大量的线程导致的
案例模拟
说明
示例代码
运行结果
分析及解决
解决方向1
解决方向2
性能优化案例
面试题
性能优化案例1:调整堆大小提高服务的吞吐量
修改Tomcat JVM配置
初始配置
查看日志
优化配置
查看日志
性能优化案例2:JVM优化之JIT优化
性能优化案例3:合理配置堆内存
特殊问题:新生代与老年代的比例
性能优化案例4:CPU占用很高排查方案
性能优化案例5:G1并发执行的线程数对性能的影响
性能优化案例6:调整垃圾回收器提高服务的吞吐量
性能优化案例7:日均百万级订单交易系统如何设置JVM参数
问题扩展
04_大厂面试题
收藏
0 条评论
下一页