赞
踩
JVM作为Java进阶的知识,是需要Java程序员不断深度和理解的。
本篇博客介绍JVM调优的相关知识,给出了一个demo案例,介绍了JVM调优的主要参数;介绍了jdk自带的jvm分析工具的使用;给出了一个内存溢出的调优场景,逐步分析定位问题,以及发生死锁的分析案例。
其他相关的JVM博客文章如下:
系列文章合集如下:
【合集】Java进阶——Java深入学习的笔记汇总 & 再论面向对象、数据结构和算法、JVM底层、多线程、类加载 …
1.JVM调优的相关知识,给出了一个demo案例;
2.JVM调优的主要参数;
3.jdk自带的jvm分析工具的使用;
3.内存溢出的调优场景,逐步分析定位问题;
4.发生死锁的分析案例
https://gitee.com/pet365/java-gc-demo
内存溢出
调用链
JDK1.8默认采用GC回收器为:PS + PO组合
如果我们不切换到G1回收器的情况下,如何进行参数调优!
什么是调优?
调优,都必须根据业务场景来调优,不能假设,假设式的调优都是耍流氓!
调优参数:java -X & java -XX
开头的这些非标准参数!
主要是java -XX开头的参数,但是没有文档信息介绍
[root@iZuf61wy7p4tbr7lmwv18iZ ~]# java -X -Xmixed 混合模式执行(默认) -Xint 仅解释模式执行 -Xbootclasspath:<用 : 分隔的目录和 zip/jar 文件> 设置引导类和资源的搜索路径 -Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件> 附加在引导类路径末尾 -Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件> 置于引导类路径之前 -Xdiag 显示附加诊断消息 -Xnoclassgc 禁用类垃圾收集 -Xincgc 启用增量垃圾收集 -Xloggc:<file> 将 GC 状态记录在文件中(带时间戳) -Xbatch 禁用后台编译 -Xms<size> 设置初始 Java 堆大小 -Xmx<size> 设置最大 Java 堆大小 -Xss<size> 设置 Java 线程堆栈大小 -Xprof 输出 cpu 分析数据 -Xfuture 启用最严格的检查,预计会成为将来的默认值 -Xrs 减少 Java/VM 对操作系统信号的使用(请参阅文档) -Xcheck:jni 对 JNI 函数执行其他检查 -Xshare:off 不尝试使用共享类数据 -Xshare:auto 在可能的情况下使用共享类数据(默认) -Xshare:on 要求使用共享类数据,否则将失败。 -XshowSettings 显示所有设置并继续 -XshowSettings:system (仅限 Linux)显示系统或容器 配置并继续 -XshowSettings:all 显示所有设置并继续 -XshowSettings:vm 显示所有与 vm 相关的设置并继续 -XshowSettings:properties 显示所有属性设置并继续 -XshowSettings:locale 显示所有与区域设置相关的设置并继续 -X 选项是非标准选项。如有更改,恕不另行通知。
-XX参数主要有3种:行为参数,调优参数,调试参数
行为参数(功能开关) -XX:-DisableExplicitGC 禁止调用System.gc();但jvm的gc仍然有效 -XX:+MaxFDLimit 最大化文件描述符的数量限制 -XX:+ScavengeBeforeFullGC 新生代GC优先于Full GC执行 -XX:+UseGCOverheadLimit 在抛出OOM之前限制jvm耗费在GC上的时间比例 -XX:-UseConcMarkSweepGC 对老年代采用并发标记交换算法进行GC -XX:-UseParallelGC 启用并行GC -XX:-UseParallelOldGC 对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用 -XX:-UseSerialGC 启用串行GC -XX:+UseThreadPriorities 启用本地线程优先级 性能调优 -XX:LargePageSizeInBytes=4m 设置用于Java堆的大页面尺寸 -XX:MaxHeapFreeRatio=70 GC后java堆中空闲量占的最大比例 -XX:MaxNewSize=size 新生成对象能占用内存的最大值 -XX:MaxPermSize=64m 老年代对象能占用内存的最大值 -XX:MinHeapFreeRatio=40 GC后java堆中空闲量占的最小比例 -XX:NewRatio=2 新生代内存容量与老生代内存容量的比例 -XX:NewSize=size 新生代对象生成时占用内存的默认值 -XX:ReservedCodeCacheSize=32m 保留代码占用的内存容量 -XX:ThreadStackSize=512 设置线程栈大小,若为0则使用系统默认值 -XX:+UseLargePages 使用大页面内存 调试参数 -XX:-CITime 打印消耗在JIT编译的时间 -XX:ErrorFile=./hs_err_pid<pid>.log 保存错误日志或者数据到文件中 -XX:-ExtendedDTraceProbes 开启solaris特有的dtrace探针 -XX:HeapDumpPath=./java_pid<pid>.hprof 指定导出堆信息时的路径或文件名 -XX:-HeapDumpOnOutOfMemoryError 当首次遭遇OOM时导出此时堆中相关信息 -XX:OnError="<cmd args>;<cmd args>" 出现致命ERROR之后运行自定义命令 -XX:OnOutOfMemoryError="<cmd args>;<cmd args>" 当首次遭遇OOM时执行自定义命令 -XX:-PrintClassHistogram 遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同 -XX:-PrintConcurrentLocks 遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同 -XX:-PrintCommandLineFlags 打印在命令行中出现过的标记 -XX:-PrintCompilation 当一个方法被编译时打印相关信息 -XX:-PrintGC 每次GC时打印相关信息 -XX:-PrintGCDetails 每次GC时打印详细信息 -XX:-PrintGCTimeStamps 打印每次GC的时间戳 -XX:-TraceClassLoading 跟踪类的加载信息 -XX:-TraceClassLoadingPreorder 跟踪被引用到的所有类的加载信息 -XX:-TraceClassResolution 跟踪常量池 -XX:-TraceClassUnloading 跟踪类的卸载信息 -XX:-TraceLoaderConstraints 跟踪类加载器约束的相关信息
可以参考:https://blog.csdn.net/geejkse_seff/article/details/124288313
java -jar -XX:+UseG1GC -Xms200m -Xmx200m -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=8 -XX:G1HeapRegionSize=16m -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=40 -XX:TargetSurvivorRatio=50 -XX:MaxTenuringThreshold=15 -XX:InitiatingHeapOccupancyPercent=45 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:/gc.log gc-1.0.jar
通过DOS命令窗口,启动jar包
java -jar -Xms200m -Xmx200M -XX:+PrintGC -XX:-UseParallelGC gc-1.0.jar
选择不安全连接
查看VM概要,有启动时设置的参数
查看控制台概览,堆内存不断增加
年轻代的gc回收
可以手动GC
另外一个工具 jvisualvm.exe
能够监测到死锁的产生
生成dump文件查看
控制台进行各种GC
垃圾回收
开始出现Full GC
此时,jvm只在回收垃圾
在Linux系统上运行:
java -jar -Xms200m -Xmx200M -XX:+PrintGC -XX:-UseParallelGC ./gc-1.0.jar
top、 jps 、jinfo、jstat 、jmap
另开一个窗口,去使用上述的命令:
内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文件等等,都可能会造成内存溢出。如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。首先,我们得先学会如何定位问题,然后再进行分析。
cpu飙升
jps
jinfo 63205 查看参数配置
[root@192 ~]# jinfo 63205 Attaching to process ID 63205, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.371-b11 Java System Properties: java.runtime.name = Java(TM) SE Runtime Environment java.vm.version = 25.371-b11 sun.boot.library.path = /root/software/jdk/jdk1.8.0_371/jre/lib/amd64 java.protocol.handler.pkgs = org.springframework.boot.loader java.vendor.url = http://java.oracle.com/ java.vm.vendor = Oracle Corporation path.separator = : file.encoding.pkg = sun.io java.vm.name = Java HotSpot(TM) 64-Bit Server VM sun.os.patch.level = unknown sun.java.launcher = SUN_STANDARD user.country = CN user.dir = /usr/local/software/jar/java-gc-demo java.vm.specification.name = Java Virtual Machine Specification PID = 63205 java.runtime.version = 1.8.0_371-b11 java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment os.arch = amd64 java.endorsed.dirs = /root/software/jdk/jdk1.8.0_371/jre/lib/endorsed line.separator = java.io.tmpdir = /tmp java.vm.specification.vendor = Oracle Corporation os.name = Linux sun.jnu.encoding = UTF-8 java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib spring.beaninfo.ignore = true java.specification.name = Java Platform API Specification java.class.version = 52.0 sun.management.compiler = HotSpot 64-Bit Tiered Compilers os.version = 3.10.0-1160.95.1.el7.x86_64 user.home = /root user.timezone = Asia/Shanghai catalina.useNaming = false java.awt.printerjob = sun.print.PSPrinterJob file.encoding = UTF-8 java.specification.version = 1.8 catalina.home = /tmp/tomcat.10050.2643101067280109420 user.name = root java.class.path = target/spring-gc-demo-1.0-SNAPSHOT.jar java.vm.specification.version = 1.8 sun.arch.data.model = 64 sun.java.command = target/spring-gc-demo-1.0-SNAPSHOT.jar java.home = /root/software/jdk/jdk1.8.0_371/jre user.language = zh java.specification.vendor = Oracle Corporation awt.toolkit = sun.awt.X11.XToolkit java.vm.info = mixed mode java.version = 1.8.0_371 java.ext.dirs = /root/software/jdk/jdk1.8.0_371/jre/lib/ext:/usr/java/packages/lib/ext sun.boot.class.path = /root/software/jdk/jdk1.8.0_371/jre/lib/resources.jar:/root/software/jdk/jdk1.8.0_371/jre/lib/rt.jar:/root/software/jdk/jdk1.8.0_371/jre/lib/jsse.jar:/root/software/jdk/jdk1.8.0_371/jre/lib/jce.jar:/root/software/jdk/jdk1.8.0_371/jre/lib/charsets.jar:/root/software/jdk/jdk1.8.0_371/jre/lib/jfr.jar:/root/software/jdk/jdk1.8.0_371/jre/classes java.awt.headless = true java.vendor = Oracle Corporation catalina.base = /tmp/tomcat.10050.2643101067280109420 java.specification.maintenance.version = 4 file.separator = / java.vendor.url.bug = http://bugreport.sun.com/bugreport/ sun.io.unicode.encoding = UnicodeLittle sun.cpu.endian = little sun.cpu.isalist = VM Flags: Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=209715200 -XX:MaxHeapSize=209715200 -XX:MaxNewSize=69730304 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=69730304 -XX:OldSize=139984896 -XX:+PrintGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC Command line: -Xms200m -Xmx200M -XX:+PrintGC
发现参数 -Xms200m -Xmx200M -XX:+PrintGC似乎并没有不合理的设置
jstat -gc 63205
jstack 63205
top -p 63205 -H
jmap -histo 4498 | head -20 #查看前20条信息
jmap -histo 63205 | head -20
剩余的工作:去调整你的业务代码,但是jmap的缺陷在于:它在导出内存图的时候,会STW,所以需要少用!
最好在测试环境中去 复盘出 生产环境的问题;然后在测试机上去使用jmap命令!
jmap -dump:format=b,file=/root/dump4498.hprof 4498 #将进程中的堆的所有信息快照出来
导出快照仍旧会导致STW问题,会导致所有业务线程卡死!
所以什么时间生成堆文件呢!
java -jar -Xms200m -Xmx200M -XX:+PrintGC -XX:-UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/root/springbootgc.hprof ./gc-1.0.jar
-XX:+HeapDumpOnOutOfMemoryError JVM由于内存不足宕机的时候,自动生成
-XX:HeapDumpPath=/root/springbootgc.hprof 堆文件的存储位置
有些时候我们需要查看下jvm中的线程执行情况,比如,发现服务器的CPU的负载突然增高了、出现了死锁、死循环等,我们该如何分析呢?由于程序是正常运行的,没有任何的输出,从日志方面也看不出什么问题,所以就需要看下jvm的内部线程的执行情况,然后再进行分析查找出原因。这个时候,就需要借助于jstack命令了,jstack的作用是将正在运行的jvm的线程情况进行快照,并且打印出来:
在Java中线程的状态一共被分成6种:
初始态(NEW):创建一个Thread对象,但还未调用start()启动线程时,线程处于初始态。
运行态(RUNNABLE):在Java中,运行态包括 就绪态 和 运行态。
阻塞态(BLOCKED):
等待态(WAITING)
超时等待态(TIMED_WAITING)
终止态(TERMINATED)
线程执行结束后的状态
jstack 63205
1.JVM调优的相关知识,给出了一个demo案例;
2.JVM调优的主要参数;
3.jdk自带的jvm分析工具的使用;
3.内存溢出的调优场景,逐步分析定位问题;
4.发生死锁的分析案例
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。