Java进阶(JVM调优) |
您所在的位置:网站首页 › java中jvm代表什么 › Java进阶(JVM调优) |
JVM作为Java进阶的知识,是需要Java程序员不断深度和理解的。 本篇博客介绍JVM调优的相关知识,给出了一个demo案例,介绍了JVM调优的主要参数;介绍了jdk自带的jvm分析工具的使用;给出了一个内存溢出的调优场景,逐步分析定位问题,以及发生死锁的分析案例。 其他相关的JVM博客文章如下: Java进阶(1)——JVM的内存分配 & 反射Class类的类对象 & 创建对象的几种方式 & 类加载(何时进入内存JVM)& 注解 & 反射+注解的案例Java进阶(4)——结合类加载JVM的过程理解创建对象的几种方式:new,反射Class,克隆clone(拷贝),序列化反序列化Java进阶(垃圾回收GC)——理论篇:JVM内存模型 & 垃圾回收定位清除算法 & JVM中的垃圾回收器系列文章合集如下: 【合集】Java进阶——Java深入学习的笔记汇总 & 再论面向对象、数据结构和算法、JVM底层、多线程、类加载 … 目录 前言引出JVM优化入门案例demo代码JVM调优参数 使用jdk自带的工具分析jconsole.exejvisualvm.exe 内存溢出的调优场景top命令发现是javajps 查看java进程jinfo 63205 查看JVM参数配置jstat 查看java进程内存分配jstack 打印出进程内部栈的调用链信息top -p 29046 -H 打印出进程内部线程的CPU占用情况jmap -histo 查看进程中的类,以及类的实例个数 发生死锁的调优场景线程的状态使用jstack进行分析 总结 引出1.JVM调优的相关知识,给出了一个demo案例; 2.JVM调优的主要参数; 3.jdk自带的jvm分析工具的使用; 3.内存溢出的调优场景,逐步分析定位问题; 4.发生死锁的分析案例 JVM优化入门 案例demo代码https://gitee.com/pet365/java-gc-demo 内存溢出 调用链 JDK1.8默认采用GC回收器为:PS + PO组合 如果我们不切换到G1回收器的情况下,如何进行参数调优! 什么是调优? 根据需求进行JVM规划&预调优JVM环境卡顿(找到系统瓶颈:压测)解决JVM运行期间的问题(内存泄漏,内存溢出……)调优,都必须根据业务场景来调优,不能假设,假设式的调优都是耍流氓! JVM调优参数调优参数:java -X & java -XX 开头的这些非标准参数! 主要是java -XX开头的参数,但是没有文档信息介绍 -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.log 保存错误日志或者数据到文件中 -XX:-ExtendedDTraceProbes 开启solaris特有的dtrace探针 -XX:HeapDumpPath=./java_pid.hprof 指定导出堆信息时的路径或文件名 -XX:-HeapDumpOnOutOfMemoryError 当首次遭遇OOM时导出此时堆中相关信息 -XX:OnError=";" 出现致命ERROR之后运行自定义命令 -XX:OnOutOfMemoryError=";" 当首次遭遇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 使用jdk自带的工具分析通过DOS命令窗口,启动jar包 java -jar -Xms200m -Xmx200M -XX:+PrintGC -XX:-UseParallelGC gc-1.0.jar jconsole.exe选择不安全连接 查看VM概要,有启动时设置的参数 查看控制台概览,堆内存不断增加 年轻代的gc回收 可以手动GC 另外一个工具 jvisualvm.exe 能够监测到死锁的产生 生成dump文件查看 控制台进行各种GC 垃圾回收 开始出现Full GC 此时,jvm只在回收垃圾 在Linux系统上运行: java -jar -Xms200m -Xmx200M -XX:+PrintGC -XX:-UseParallelGC ./gc-1.0.jartop、 jps 、jinfo、jstat 、jmap 另开一个窗口,去使用上述的命令: 内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文件等等,都可能会造成内存溢出。如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。首先,我们得先学会如何定位问题,然后再进行分析。 cpu飙升 jps jinfo 63205 查看参数配置 发现参数 -Xms200m -Xmx200M -XX:+PrintGC似乎并没有不合理的设置 jstat 查看java进程内存分配 jstat -gc 63205jmap -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中,运行态包括 就绪态 和 运行态。 就绪态:该状态下的线程已经获得执行所需的所有资源,只要CPU分配执行权就能运行,所有就绪态的线程存放在就绪队列中运行态:获得CPU执行权,正在执行的线程,由于一个CPU同一时刻只能执行一条线程,因此每个CPU每个时刻只有一条运行态的线程阻塞态(BLOCKED): 当一条正在执行的线程请求某一资源失败时,就会进入阻塞态。而在Java中,阻塞态专指请求锁失败时进入的状态。由一个阻塞队列存放所有阻塞态的线程。处于阻塞态的线程会不断请求资源,一旦请求成功,就会进入就绪队列,等待执行。等待态(WAITING) 当前线程中调用wait、join、park函数时,当前线程就会进入等待态。也有一个等待队列存放所有等待态的线程。线程处于等待态表示它需要等待其他线程的指示才能继续运行。进入等待态的线程会释放CPU执行权,并释放资源(如:锁)超时等待态(TIMED_WAITING) 当运行中的线程调用sleep(time)、wait、join、parkNanos、parkUntil时,就会进入该状态;它和等待态一样,并不是因为请求不到资源,而是主动进入,并且进入后需要其他线程唤醒;进入该状态后释放CPU执行权 和 占有的资源。与等待态的区别:到了超时时间后自动进入阻塞队列,开始竞争锁。终止态(TERMINATED) 线程执行结束后的状态 使用jstack进行分析 jstack 632051.JVM调优的相关知识,给出了一个demo案例; 2.JVM调优的主要参数; 3.jdk自带的jvm分析工具的使用; 3.内存溢出的调优场景,逐步分析定位问题; 4.发生死锁的分析案例 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |