首页 > 其他分享 >JVM调优(十七)JVM常见调优问题和工具的使用

JVM调优(十七)JVM常见调优问题和工具的使用

时间:2023-08-16 21:00:23浏览次数:25  
标签:十七 java 调优 线程 JVM 使用 进程

JVM调优(十七)JVM常见调优问题和工具的使用


说辞

  • 熟悉GC常见算法
  • 熟悉常见的垃圾回收器,具有实际JVM调优经验

1 什么是调优

  • 根据需求进行JVM优化和预调优
  • 优化JVM的运行环境(慢、卡顿)
  • 解决JVM运行过程中出现的各种问题(OOM)

2 JVM常用调优命令

  • jpsJDK自带,全称java process,列出系统中运行的所有java进程

  • jinfoJDK自带,jinfo port,列出端口号对应jvm的详细信息,包括如

    • jvm版本
    • 操作系统和编码信息
    • 虚拟机参数(VM Flags):初始堆大小、最大堆大小以及设置的命令行参数等
  • jstatJDK自带,

    • jstat -gc port:打印jvm的内存使用情况
    • jstat -gc port time:实时监测JVM内存使用情况,每time ms打印一次

    image-20230815101358645

  • topLinux命令,打印出目前系统进程的资源使用情况,可以定位哪些进程在消耗资源,在实际开发过程中,一般会进行系统的监控,使用Zabbix+Promethems来进行系统的监控报警

    • top -Hp port打印端口号下的所有线程的资源使用情况
    • -d:指定top命令间隔几秒钟更新,默认为3秒
    • -i:使top不显示任何闲置或者僵死进程
    • -p:通过进程id仅仅监视某个进程
  • jstackJDK自带,追踪java线程的资源使用情况,包括线程的名字、线程的状态、线程调用的方法堆栈,jstack一般用于查找具体的哪些java线程在占用内存、cpu甚至出现死锁

    • 阿里编码规范中就规定每个线程都必须起一个有意义的名字,方便进行jstack回溯
    image-20230815102919898
  • jmap -histo pid:主要用于查看pid的java进程对应的JVM中加载了哪些类,然后用这些类又创建了多少对象

    image-20230816091343910
1.1 jmap
  • jmap -histo port:主要用于查看port端口下的java进程对应的JVM中加载了哪些类,然后用这些类又创建了多少对象
  • jmap -dumy:format=b,file=2023.8.13.hprof pid:将当前pid的java进程的JVM转储为一个文件,然后使用一些图形化工具对转储文件进行分析即可,也可以使用jhat命令针对转储文件生成一个网页分析,常见的图形化分析工具有:
    • MAT
    • MemoryInitializeTool
    • Jprofile(收费)
    • jvisualVM(JDK自带):使用流程在下面

3 调优工具

  • Jconsole
  • JvisualVM
  • Jprofiler
  • Java Flight Recorder
  • GCViewer
  • GC Easy
3.1 jvisualVM
转储文件分析
  • 首先将jmap生成的转储文件装入jvisualVM,然后软件会分析出快照文件的一些基本信息和环境信息,以及转储文件上的线程信息

  • 然后也会有加载到该快照JVM的类信息和对应该类创建的实例的数量

  • 也可以通过一些OQL(Object Query Language)查询语句,查询JVM堆中包含某个类的所有对象信息以及产生该对象的方法信息

    select * from java.lang.String
    
监控、线程和抽样器
  • 可以远程监控进程CPU和堆的一个使用情况以及装入的进程和线程的总数

    image-20230816100623573
  • 抽样器则可以针对CPU和内存进行抽样得到类名及其使用的资源情况

    image-20230816100652148

4 实际开发的JVM调优

其实上面面这些远程的图形化调优工具在生产过程中很少使用,因为

  • 远程监控的话需要服务器开启端口号并设置防火墙
  • 远程执行如jmap命令,会进行STW让堆暂停,然后导出堆快照文件再让jvm运行,肯定会对线上运行的进程造成冲击
1 怎么在不影响线上服务的情况下进行JVM问题排查调优呢?

解决方案主要有:

  • 在启动JVM的时候设置参数HeapDumpOnMemoryError,可以在内存异常停顿的时候,自动转存堆的快照文件,方便在系统运行的时候进行日志的解析排查问题而不影响线上的环境:

    java -XX:PrintGCDetail -XX:HeapDumpOnMemoryError
    
  • 对于高可用的服务集群,集群之间互为备份,则可以先停掉一个服务,然后使用jmap命令生成dump文件,然后再使用相关工具进行解析排查

  • 在备用服务器上进行压测的时候进行

  • 使用阿里的Arthas进行线上监控

  • 在服务接收请求的时候,使用比如网易的TCPCopy将请求复制一份打到备用服务器,然后在备用服务器上进行相关的监控操作和问题排查

2 阿里Arthas
  • 启动Arthas,一般使用shell脚本或者直接命令行的方式进行启动

    java - jar arthas-boot.jar
    
  • 启动之后Arthas就会监测到系统当前正在运行的Java进程,会携带一个内部编号

  • 输入想要监控的进程的内部编号,Arthas即可挂到该进程上,对进程进行了一系列的监测和影响

    image-20230816150340745
  • Arthas常用命令:

    • dashboard:图形化显示出所有进程的运行情况,包括哪些进程在占用CPU、内存的使用情况以及整个进程的参数情况

      image-20230816151047388
    • Thread:列出当前进程运行的所有线程的状态和资源使用情况

      image-20230816152402198

      thread id:列出指定线程id的线程的方法调用情况,类似于jstack

      image-20230816152548509

    • thread -b:检查当前进程是否存在死锁

    • heap dumy:等同于jmap,即对堆内存进行文件转储

    • jad 全类名:打印出加载该类的类加载器存在的系统位置以及对源代码进行反编译的结果

      源代码的反编译结果有什么用呢?

      • 对于产生的动态代理的类,就可以使用反编译检查是否正确
      • 使用反编译可以检查代码类的版本

      image-20230816153631807

    • redfine /xxxx.java可以在服务不重启的情况下,对运行的程序进行源代码替换

      太牛了

    • trace className classMethod:单机情况下,追踪指定方法的调用的时间和其他方法的调用情况,一般用于全链路追踪&压测,如下A方法调用过程中,1000ms用于本方法执行,5004ms用于调用B方法

      image-20230816164642229

5 JVM堆设置参数

堆空间大小设置:

  • -Xms 设置堆空间(新生代+老年代)的初始内存大小
    • -X 是jvm的运行参数
    • ms 是memory start的缩写
  • -Xmx:设置堆空间(新生代+老年代)的最大内存大小

一般情况下JVM的初始堆大小和最大堆大小设置相同的值,原因是:

  • 防止内存震荡和内存抖动
  • 如果初始堆大小小于最大的大小,那么随着程序的运行堆会进行空间的拓展和收缩,JVM就会消耗时间去计算空间的拓展和收缩造成浪费

6 OOM定位排查总结

  • jps、top查看当前系统运行的java进程及其资源使用情况

  • jstat -gc port:打印jvm的内存使用情况

  • jstackJDK自带,追踪java线程的资源使用情况,包括线程的名字、线程的状态、线程调用的方法堆栈,jstack一般用于查找具体的哪些java线程在占用内存、cpu甚至出现死锁

  • jmap -histo port主要用于查看port端口下的java进程对应的JVM中加载了哪些类,然后用这些类又创建了多少对象

  • 先通过jmap生成jvm转储文件,然后使用一些图形化工具对转储文件进行分析

  • 经过上面几种工具的使用,基本能够定位到导致出现OOM的地方了

7 CPU标高,如何定位?

  • 首先通过系统的top命令、堆转储文件或者Arthas的实时监控查看是哪个线程在占用CPU

  • 然后如果这个线程是业务线程,就说明业务代码有问题,比如导致出现死循环、CPU大量计算等情况,需要去使用比如jstack命令或者Arthas的thread命令追踪java线程的资源使用情况,(jstack命令包括线程的名字、线程的状态、线程调用的方法堆栈,jstack一般用于查找具体的哪些java线程在占用内存、cpu甚至出现死锁

  • 而如果线程是GC线程,那就说明系统在频繁地Full GC回收,那么这时候就需要去查看GC日志,看看是否在频繁回收,查看回收情况,如果每次回收还是正常回收说明当前系统的请求压力很大不一定是系统存在问题,而如果每次都回收不掉只回收很少的空间,则说明出现内存泄露了

  • 压力很大该怎么办。。

  • 内存泄露该怎么办。。

标签:十七,java,调优,线程,JVM,使用,进程
From: https://www.cnblogs.com/tod4/p/17636170.html

相关文章

  • JVM相关面试题
    JVM的组成程序计数器Java堆虚拟机栈其实就是线程运行时需要的内存......
  • 性能测试报告:用于项目的性能验证、性能调优、发现性能缺陷等应用场景
     性能测试报告是一种重要的报告类型,旨在评估软件系统的性能、稳定性和安全性。在这篇文章中,我们将详细介绍性能测试报告的应用场景、测试方法和性能指标,以及如何撰写一份有效的性能测试报告。一、概述性能测试报告的目的是对软件系统的性能进行全面的评估,以便更好地进行性能......
  • .Net的性能调优
    .Net的性能调优一、.NetCore中的内存泄露1.1什么是内存溢出和内存泄露什么叫内存泄露(memoryleak)是指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收并不会到程序造成什么影响,但是如果在内存本身就......
  • (十七)MIT公开课雷达系统工程之参数估计与跟踪 (上)
    0写在前面只有走在路上,才能摆脱局限、摆脱执着,让所有的选择、探寻、猜测、想象都生机勃勃。——余秋雨《文化苦旅》1基本介绍跟踪雷达:雷达参数估计:准确度、精度和分辨率:2ObservableEstimationObservableAccuracy:LimitationsonRangeEstimation:Theoreticalvs.PracticalAc......
  • Amazon EMR Hudi 性能调优——Clustering
    随着数据体量的日益增长,人们对Hudi的查询性能也提出更多要求,除了Parquet存储格式本来的性能优势之外,还希望Hudi能够提供更多的性能优化的技术途径,尤其当对Hudi表进行高并发的写入,产生了大量的小文件之后,又需要使用Presto/Trino对Hudi表进行高吞吐的即席查询的场景里。......
  • JVM相关
    对象头在JVM中,对象在内存中的布局分为3块:对象头、实例数据和对齐填充。实例数据:程序代码中定义的各种类型的字段内容。对齐填充:JVM要求对象的大小必须是8个字节的整数倍,对象头已经是8的整数倍了,如果实例数据没有8的整数倍就需要对齐填充来补全。对象头=MarkWord+类型......
  • 形象谈JVM-第二章-认识编译器
    我在上一章《形象谈JVM-第一章-认识JVM》提到的“翻译”,其实就是我们今天所说的“编译”的概念。上一章原文链接:https://www.cnblogs.com/xingxiangtan/p/17617654.html原文:【虚拟机的职责是将字节码翻译成对应系统能够识别并执行的机器码,比如在linux系统,java文件被javac编译......
  • Java | JDK、JRE、JVM的关系
    一、什么是JDK、JRE、JVM?JDK(JavaDevelopmentKitJava开发工具包)是提供给Java开发人员使用的,其中包含了java的开发工具集,也包括了java的运行环境JRE。它是开发者在进行Java应用程序开发时所需的完整套件。JRE(JavaRuntimeEnvironmentJava运行环境)包括java虚拟机和Java程......
  • JVM——内存分配与垃圾回收
    内存分配与垃圾回收1、jvm简介Java虚拟机在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域。它们各有用途,有些随着虚拟机进程的启动一直存在(堆、方法区),有些则随着用户线程的启动和结束而建立和销毁(程序计数器、虚拟机栈、本地方法栈)。JVM的设计者们之所......
  • JVM——类加载机制
    任何一个类型在使用之前都必须经历过完整的加载、连接和初始化3个类加载步骤。一旦一个类型成功经历过这3个步骤之后,它就可以随时随地被使用了,开发人员可以在程序中访问和调用它的静态类成员信息(比如:静态方法、静态字段),或者使用new关键字为其创建对象实例。当然从一个类型被加载进......