一、JVM概述
1、为什么要调优
1、防止出现OOM
2、解决OOM问题
3、减少Full GC频率
4、提高系统稳定性
2、性能优化的步骤
1)性能监控
主要监控GC频率、CPU、OOM问题、内存泄露、死锁、程序响应时间等问题;
2)性能分析
1、使用http://gceasy.io来分析GC日志
2、灵活使用命令行工具:jps、jstack、jstat、jmap、jinfo等
3、导出dump文件,使用内存分析工具分析
4、使用Arthas、jconsole、JVisualVM等工具实事查看JVM状态
3)性能调优
1、增加内存
2、优化代码
3、增加机器,分散服务器压力
4、合理分配线程数量
5、使用中间件进行缓存
4、性能指标
1、响应时间
2、吞吐量
3、并发数
4、内存占用
二、JVM监控及诊断之命令
1、jps(Java Process Status)
1)用途:
1、查看正在运行的Java进程
2)基本语法
jps [options] [hostid]
options参数:
-q:仅仅显示本地虚拟机id
-l:输出应用程序全类名
-m:列出虚拟机进程启动时传递主类的main()的参数
-v:列出虚拟机进程启动时的JVM参数
2、jstat(JVM Statistics Monitoring Tool)
1)用途:
1、用于监视虚拟机各种运行状态信息的命令行工具,可以显示本地或者远程中的类装载、内存、垃圾收集、JIT等状态;
2)基本语法
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
option参数:
> 类装载相关的:
-class:显示ClassLoader的相关信息: 类的装载、卸载数量、总空间、类装载所消耗的时间等;
> 垃圾回收相关的:
-gc:显示与GC相关的堆信息,包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息
-gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间
-gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
-gccause:与-gcutil功能一-样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因
-gcnew:显示新生代GC状况
-gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
-geold:显示老年代GC状况
-gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
-gcpermcapacity:显示永久代使用到的最大、最小空间
> JIT相关的:
-compiler:显示JIT编译器编译过的方法、耗时等信息
-printcompilation:输出已经被JIT编译的方法
interval参数:用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
count参数:用于查询的总次数
-t:可以在输出信息前加上一个Timestamp列,显示程序的运行时间。单位:秒
-h:可以在周期性数据输出时,输出多少行数据后输出一个表头信息
3、jinfo(Configration Info for Java)
1)用途:
1、查看虚拟机配置参数信息,也可用于调整虛拟机的配置参数。
2)基本语法
jinfo [options] pid
查看配置信息:
jinfo sysprops <进程ID> # 可以查看由System.getProperties()取得的参数
jinfo flags <进程ID> # 查看曾经赋过值的一些参数
jinfo flag <进程ID> # 查看某个Java进程的具体参数
修改配置信息:
jinfo -flag [+|-]参数名称 <进程ID>
jinfo -flag 参数名称=参数值 <进程ID>
拓展:
java -XX:+PrintFlagsInitial # 查看所有JVM参数启动的初始值
java -XX:+PrintFlagsFinal # 查看所有JVM参数的最终值
java -参数名称 +PrintCommandLineFlags # 查看哪些已经被用户或者JVM设置过的参数的名称和值
4、jmap(Java Memory map)
1)用途:
1、导出dump文件,获取java进程的内存相关信息;
2)基本语法
jmap [option] <pid>
option参数:
-dump:生成Java堆快照文件
-heap:输出整个堆空间的详细信息,包括GC的使用.堆配置信息,以及内存的使用信息等
-histo:输出堆中对象的同级信息,包括类、实例数量和合计容量
-permstat:以ClassLoader为统计口径输出永久代的内存状态信息(仅linux/solaris平台有效)
-finalizerinfo:显示在F-Queue中等待Finalizer线程执行finalize方法的对象(仅linux/solaris平台有效)
-F:强制生成dump文件
> 导数内存映射文件:
手动方式:
jmap dump:format=b,file=<filename.hprof> <pid>
jmap dump:live,format=b,file=<filename.hprof> <pid>
自动方式:
-XX:HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=<filename.hprof>
5、jhat(JVM Heap Analysis Tool)
1)用途:
1、JDK自带堆分析工具
2)基本语法
jhat [option] [dumpfile]
option参数:
-stack false|true # 关闭|打开对象分配调用栈跟踪
-refs false|true # 关闭|打开对象引用跟踪
-port port-number # 设置 jhat HTTP Server 端口号,默认7000
-exclude exclude-file # 执行对象查询时需要排除的数据成员
-baseline exclude-file # 指定一个基准堆转储
-debug int # 设置debug级别
6、jstack(Java Stack Trace)
1)用途:
1、打印jvm中线程快照
2)基本语法
jstack [option] <pid>
-F:当正常输出的请求不被响应时,强制输出线程堆栈
-l:除堆栈外,显示关于锁的信息
-m:如果调用本地方法的话,可以显示C/C++的堆栈
7、jcmd(Java Command)
1)用途:
1、多功能命令行,可以实现除了jstat之外的所有命令的功能
2)基本语法
jcmd -l # 列出所有JVM进程
jcmd 进程号 help # 针对指定的进程,列出支持的所有具体命令
jcmd 进程号 具体命令 # 显示指定进程的指定命令的数据
8、jstatd(Java Statistics Monitoring Daemon)
1)用途:
1、远程主机信息收集,此命令是一个RMI Server应用程序,提供了对JVM的创建和结束监视,也为远程监视工具提供了一个可以attach的接口
2)基本语法
jstatd [options]
options参数:
-nr # 当一个存在的RMI Registry没有找到时,不尝试创建一个内部的RMI Registry
-p port # 端口号,默认为1099
-n rminame # 默认为JStatRemoteHost;如果多个jstatd服务开始在同一台主机上,rminame唯一确定一个jstatd服务
-J # jvm选项
三、JVM常用GUI工具
1、JDK自带工具
1、jconsole:JDK自带的可视化监控工具,查看Java应用程序的运行概况、监控堆信息、永久区(或元空间)使用情况、类加载情况等;
2、Visual VM:Visual VM是一个工具,它提供了一个可视界面,用于查看Java虚拟机上运行的基于Java技术的应用程序的详细信息;
3、JMC:Java Mission Control,内置Java Flight Recorder,能够以极低的性能开销收集Java虚拟机的性能数据。
2、第三方工具
1、MAT
2、JProfiler
四、JVM常用参数
1、JVM参数类型
类型一:标准参数选项
1、以 - 开头
2、Hotspot VM有两种模式,分别是server和client
类型二:-X参数选项
1、以-X开头
2、JVM的JIT编译模式相关的选项:-Xint解释模式、-Xcomp编译模式、-Xmixed混合模式
3、-Xms -Xmx -Xss参数分别是-XX:InitialHeapSize、-XX:MaxHeapSize、-XX:ThreadStackSize的缩写
类型三:-XX参数选项
1、以-XX开头
2、Boolean类型:
-XX:+<option> # 表示启用option属性
-XX:-<option> # 表示禁用option属性
3、非Boolean类型:
-XX:<option>=<number>
-XX:<option>=<string>
4、-XX:+PrintFlagsFinal
输出所有参数的名称和默认值
默认不包括Diagnostic和Experimental的参数
可以配合-XX:+UnlockDiagnosticVMOptions和-XX:UnlockExperimentalVMOptions使用
2、常用JVM参数选项
1、打印设置的-XX选项及值
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsInitial
-XX:+PrintFlagsFinal
-XX:+PrintVMOptions
2、堆、栈、方法区等内存大小的设置
> 栈:
-Xss1024k # 设置每个线程的栈大小
> 堆:
-Xms1024k # 初始堆大小
-Xmx1024k # 最大堆大小
-Xmn1024k # 设置年轻代初始值和最大值都是1024k
-XX:NewSize=1024m # 新生代初始值大小
-XX:MaxNewSize=1024m # 新生代最大值大小
-XX:SurvivorRatio=8 # 新生代中Eden区和Survivor区的比值,默认为8
-XX:+UserAdaptiveSizePolicy # 自动选择区大小比例,默认开启
-XX:NewRatio=2 # 设置新生代与老年代的比值,默认为2
-XX:PretenureSizeThreadshold=1024 # 设置大于此阈值对象直接分配到老年代,单位字节(只对Serial、ParNew收集器有效)
-XX:MaxTenuringThreshold=15 # 新生代每次MinorGC后,存活对象age+1,当对象年龄大于设置的这个值时就进入老年代 ,默认15
-XX:+PrintTenuringDistribution # 让JVM在每次MinorGC后打印出当前使用的Survivor对象的年龄分布
-XX:TargetSurvivorRatio # 表示MinorGC结束后Survivor区域中占用空间的期望比例
> 方法区:
永久代:
-XX:PermSize=256m # 设置初始值大小
-XX:MaxPermSize=256m # 设置最大值大小
元空间:
-XX:MetaspaceSize # 初始值大小
-XX:MaxMetaspaceSize # 最大值大小
-XX:+UseCompressedOops # 使用压缩对象指针
-XX:+UserCompressedClassPointers # 使用压缩类指针
-XX:CompressedClassSpaceSize # 设置Class Metaspace的大小,默认1G
> 直接内存
-XX:MaxDirectMemorySize # 指定内存容量,默认和堆最大值一样
3、OOM相关选项
-XX:+HeapDumpOnOutMemoryError # 内存出现OOM时,生成Dump文件
-XX:+HeapDumpBeforeFullGC # 出现FullGC之前,生成Heap转储文件
# -XX:+HeapDumpOnOutMemoryError与-XX:+HeapDumpBeforeFullGC两者只能设置一个
-XX:HeapDumpPath=<path> # 指定Heap转储文件路径
-XX:OnOutOfMemoryError # 当发生OOM时,指定一个脚本路劲,并执行这个脚本
4、垃圾收集器相关选项
5、GC日志相关选项
常用参数:
-verbose:gc # 输出日志信息,默认标准输出
-XX:+PrintGC # 打印简化版GC日志
-XX:+PrintGCDetails # 打印GC详细日志
-XX:+PrintGCTimeStamps # 程序启动到发生GC的时间秒数
-XX:+PrintGCDateStamps # 输出GC发生的时间戳,必须配合-XX:PrintGCDeails使用
-XX:+PrintHeapAtGC # 每次GC前和GC后,都打印堆信息
-Xloggc<file> # 把GC日志写入一个文件中
其他参数:
-XX:TraceClassLoading # 监控类的加载
-XX:PrintGCApplicationStoppedTime # 打印GC时线程的停顿时间
-XX:+PrintGCApplicationConcurrentTime # 垃圾收集之前打印出应用未中断的执行时间
-XX:+PrintReferenceGC # 记录回收了多少种不同引用类型的引用
-XX:PrintTenuringDistribution # 让JVM在每次MinorGC后打印出当前使用的Survivor中对象的年龄分布
-XX:+UseGCLogFileRotation # 启用GC日志文件的自动转储
-XX:NumberOfGCLogFiles=1 # GC日志文件的循环数目
-XX:GCLogFileSize=1M # 控制GC日志文件的大小
6、其他参数
-XX:+DisableExplicitGC # 禁用hotshot执行System.gc,默认禁用
-XX:ReservedCodeCacheSize=<size>[G|M|K] # 指定代码缓存大小
-XX:+UseCodeCacheFlushing # 使用该参数让JVM放弃一些被编译的代码,避免代码缓存被占满时JVM切换到interpreted-only的情况
-XX:+DoEscapeAnalysis # 开启逃逸分析
-XX:+UseBiasedLocking # 开启偏向锁
-XX:+UseLargePages # 开启使用大页面
-XX:+PrintTLAB # 打印TLAB的使用情况
-XX:TLABSize # 设置TLAB的大小