一文搞懂:Java项目线上故障处理和调优的基本方法

news2024/11/25 15:41:18

一. 调优和故障处理的方向

Java调优通常指的是对Java应用程序进行性能优化和资源管理的过程。调优的方向很多也很广,比如:

  • 内存管理:优化Java应用程序的内存使用,包括减少内存泄漏、合理设置堆大小、优化垃圾收集器的选择和参数配置等。
  • 线程管理:通过优化线程使用方式,避免过多线程竞争和线程阻塞,提高多线程应用程序的性能和稳定性。
  • IO操作:优化文件和网络IO操作,避免阻塞和资源浪费,提高IO操作的效率。
  • 数据库访问:优化数据库访问的性能,包括减少数据库连接的创建和关闭、合理利用数据库连接池等。
  • 算法和数据结构:优化算法和数据结构的选择和实现,提高程序的执行效率和资源利用率。
  • JVM调优:通过调整JVM的参数和配置,优化Java应用程序在JVM上的运行性能,包括堆大小、垃圾收集器、JIT编译器等。

本文主要指的是:内存管理线程管理JVM调优 这几个方面。

线上(生产环境)故障指的是在实际运行中出现的影响系统正常功能的问题或错误,这些问题可能导致系统停止响应、性能下降、功能异常、数据丢失等不良后果。人为的代码bug造成的业务bug等,不在本篇中,本篇主要是指比如:OOM异常机器内存耗尽机器CPU飙升访问超时快速定位等等。

写在前面:如果出现问题,最快速的方式就是看日志(前提是能看到),所以建议做好生产环境的日志打印;本篇只是讲一些基本的操作方式,正常环境需要有全面的认知和灵活的应用

所以建议生产环境启动时加上以下参数,免得出问题了找不到日志:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/app/appDump.dump		//堆转储文件的路径   自定义
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-XX:+PrintHeapAtGC
-XX:+PrintReferenceGC
-XX:+PrintGCApplicationStoppedTime
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=14
-XX:GCLogFileSize=100M
-Xloggc:/tmp/gc-%t.log   	// GC 日志文件的路径  自定义

二. 常用JDK自带的命令工具介绍

1. jps

jps命令主要用来查看JVM进程状态:

  • jps -m 显示传递给main方法的参数
  • jps -l 显示应用main class的完整包应用的jar文件完整路径名
  • jps -v 显示传递给JVM的参数
    例子:
    在这里插入图片描述
    在这里插入图片描述
    命令也可以组合使用在这里插入图片描述

2. jstat

jstat(JVM Statistics Monitoring Tool) 使用于监视虚拟机各种运行状态信息的命令行工具:

  • jstat -gc <pid>:显示与 GC 相关的堆信息
  • jstat -gccapacity <pid>:显示各个代的容量及使用情况
  • jstat -gcnew <pid>:显示新生代信息
  • jstat -gcnewcapcacity <pid>:显示新生代大小与使用情况
  • jstat -gcold <pid>:显示老年代和永久代的行为统计,从 jdk1.8 开始,该选项仅表示老年代,因为永久代被移除了
  • jstat -gcoldcapacity <pid>:显示老年代的大小
  • jstat -gcutil <pid>:显示垃圾收集信息
  • jstat -class <pid>:显示 ClassLoader 的相关信息
  • jstat -compiler <pid>:显示 JIT 编译的相关信息

<pid> 表示要查看的进程id,就是jps命令中的进程号。例如:
在这里插入图片描述

3. jinfo

jinfo <pid>命令用于输出当前 jvm 进程的全部参数和系统属性,第一部分是系统的属性,第二部分是 JVM 的参数。
jinof -flag <name> :用于指定输出某个参数,name表示参数名字。
例如:
查看对应进程的最大堆内存大小:
在这里插入图片描述
查看线程栈大小:
在这里插入图片描述

4. jmap

jmap(Memory Map for Java)命令用于生成堆转储快照。 如果不使用 jmap 命令,要想获取 Java 堆转储,可以在启动命令中添加 -XX:+HeapDumpOnOutOfMemoryError ,虚拟机会在发生 OOM 异常出现之后自动生成 dump 文件,Linux 命令下可以通过 kill -3 <pid> 发送进程退出信号也能拿到 dump 文件。
栗子:获取2336的Java进程的堆转储文件,jmap -dump:live,format=b,file=appDumpFile.hprof 2336,这个命令中-dump表示连接到正在运行的进程,并转储Java堆;live表示指定时,仅Dump活动对象;如果未指定,则转储堆中的所有对象;format=b表示以hprof格式Dump堆;file=filename表示堆Dump存储的路径和文件名;最后的2336是例子的pid
在这里插入图片描述
如上图所示,会在机器的/root目录下生成一份appDumpFile.hprof文件,这个文件就是2336的Java进程的堆转储文件。如果想控制生成的路径,可以自行修改file=/xxx/xxxx/fileName.hprof

5. jstack

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合.生成线程快照的目的主要是定位线程长时间出现停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者在等待些什么资源。
在实际项目中,如果你的应用出现长时间等待的时候,可以考虑使用jstack,比方说:线程死锁死循环远程请求长时间得不到返回等,都可能会出现线程长时间的等待,那么使用jstack可以得到每个线程的调用信息,这样就可以知道那些没有响应的线程在后台到底做什么或者正在等待什么样的资源。

  • jstack <pid> 生成虚拟机当前时刻的线程快照
  • jstack -l <pid> 显示有关锁的额外信息
  • jstack -F <pid> 当正常输出的请求不被响应时,强制输出线程堆栈
  • jstack -m <pid> 如果调用到本地方法的话,可以显示C/C++的堆栈

下面通过一个人为的死锁来演示一下通过jstack命令来查看死锁问题;
先看死锁代码:

public class DeathLockTest {
    private static Lock lock1 = new ReentrantLock();
    private static Lock lock2 = new ReentrantLock();
    
    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    lock1.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock1");
                    Thread.sleep(1000);
                    lock2.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    lock2.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock2");
                    Thread.sleep(1000);
                    lock1.lock();
                    System.out.println(Thread.currentThread().getName() + " get the lock1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t1.setName("myLockThread-1");
        t2.setName("myLockThread-2");
        t1.start();
        t2.start();
    }
}

由于代码为演示代码,所以我在windows电脑上进行操作:
在这里插入图片描述
首先通过jps命令获取到进程的pid,然后通过jstack <pid>命令查看当前进程的线程信息,在输出信息中可以看到线程的运行状态等各种信息,在后续的输出中可以看到:
在这里插入图片描述
就可以看出来是我们的DeathLockTest类的21行和35行发生了死锁。
这里先演示一下jps命令的方法,本文后续会通过cpu飙升来演示linux的top命令查看故障的方式。

6. jconsole

JConsole 是基于 JMX 的可视化监视、管理工具。可以很方便的监视本地及远程服务器的 java 进程的内存使用情况。
比如我windows本地jdk安装目录在:C:\Program Files\Java\jdk1.8.0_131,那么jconsole.exe就在C:\Program Files\Java\jdk1.8.0_131\bin目录下。
双击jconsole.exe即可打开:
在这里插入图片描述
打开的界面会自动列出本地的java进程,还可以远程连接其他服务器的Java进程。如果你需要远程连接访问,那么需要在被连接的项目启动时加上如下参数:

-Djava.rmi.server.hostname=外网ip地址
-Dcom.sun.management.jmxremote.port=60001   //监控的端口号
-Dcom.sun.management.jmxremote.authenticate=false   //关闭认证
-Dcom.sun.management.jmxremote.ssl=false

在使用JConsole 远程连接时,远程进程地址为:外网ip地址:60001,就是hostname:port
此处以本地服务为例,进入后为:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到JConsole 通过可视化的方式提供了Java程序运行时的各种信息,我们可以查看各种内存使用情况和线程情况,可以手动触发FullGC,可以检查死锁,还可以查看运行时的类加载信息等等,可以有效的帮助我们了解运行时的各种情况。

7. VisualVM

VisualVM(All-in-One Java Troubleshooting Tool)是到目前为止随 JDK 发布的功能最强大的运行监视和故障处理程序,官方在 VisualVM 的软件说明中写上了“All-in-One”的描述字样,预示着他除了运行监视、故障处理外,还提供了很多其他方面的功能,如性能分析(Profiling)。VisualVM 的性能分析功能甚至比起 JProfiler、YourKit 等专业且收费的 Profiling 工具都不会逊色多少,而且 VisualVM 还有一个很大的优点:不需要被监视的程序基于特殊 Agent 运行,因此他对应用程序的实际性能的影响很小,使得他可以直接应用在生产环境中。这个优点是 JProfiler、YourKit 等工具无法与之媲美的。

VisualVM 和JConsole 一样都在jdk的bin目录下,双击jvisualvm.exe即可打开。
在这里插入图片描述
可以看到VisualVM 也可以查看Java进程运行时的信息或者执行GC,但是多了一个堆dump功能(仅本地进程可使用,远程进程无此功能),点击之后会生成一份当前Java进程的dump文件:
在这里插入图片描述

这里可以很清楚的看到dump文件中的各种信息,尤其是类信息,当发生OOM等内存问题时,一般都可以在这里看到异常。比如我们发现某个类内存占用特别高或者有异常,那么可以双击这个类,比如上图中圈起来的java.lang.String,就可以详细的查看这个类的所有实例信息:
在这里插入图片描述
通过这个功能可以很方便的让我们查看类的各种实例信息,分析内存溢出、内存泄漏等问题。

个人觉得VisualVM 功能比JConsole 强大,但是单独看内存使用情况的话,JConsole 更方便直观一些。
但是VisualVM 也可以用来分析已有的其他dump文件,比如我们使用jmap命令导出了一份dump.hprof文件,此时我们点击VisualVM 左上角菜单栏的“文件”,选择:“装入”
在这里插入图片描述
在这里插入图片描述
即可打开单独的dump文件查看信息,与上面堆dump功能查看dump文件一样。

8. MAT(MemoryAnalyzer Tool)

MAT(全名:Memory Analyzer Tool),是一款快速便捷且功能强大丰富的 JVM 堆内存离线分析工具。其通过展现 JVM 异常时所记录的运行时堆转储快照(Heap dump)状态(正常运行时也可以做堆转储分析),帮助定位内存泄漏问题或优化大内存消耗逻辑。
下载地址:https://eclipse.dev/mat/previousReleases.php,记着自己的jdk是哪个版本,就下载对应版本号的,比如jdk8的就下载:
在这里插入图片描述
下载后解压,双击文件夹中的MemoryAnalyzer.exe就可以打开了。打开后选择
在这里插入图片描述
可以用来打开我们之前到处的dump文件,打开后如下:
在这里插入图片描述
这个页面展示了dump文件的基本信息统计。
我们常用的功能主要是:HistogramDominator Treethread_overview,Leak Suspects
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • Histogram:列出内存中的对象,对象的个数以及大小。Histogram在类的角度上进行分析,注重量的分析。
  • Dominator Tree:列出最大的对象以及其依赖存活的Object (大小是以Retained Heap为标准排序的),是在对象实例的角度上进行分析,注重引用关系分析。它按对象的 Retain Heap 排序,也支持按多个维度聚类统计。
  • thread_overview:查看当前进程dump时的所有线程的堆栈信息,通过分析堆栈信息可以快速定位到对应的线程所执行的方法等层级关系,以此来定位对应的异常问题
  • Leak Suspects:用于查找内存泄漏问题,以及系统概览

MAT的功能很强大,本篇就不详细讲述了,总之MAT可以帮我们分析:

  • 内存溢出,JVM堆区或方法区放不下存活及待申请的对象。如:高峰期系统出现 OOM(Out of Memory)异常,需定位内存瓶颈点来指导优化。
  • 内存泄漏,不会再使用的对象无法被垃圾回收器回收。如:系统运行一段时间后出现 Full GC,甚至周期性 OOM 后需人工重启解决。
  • 内存占用高,如:系统频繁 GC ,需定位影响服务实时性、稳定性、吞吐能力的原因。
  • 性能优化,如:内存分配调整等等

具体资料大家可以自行搜索MAT相关内容学习。

9. gceasy

这是一个网站:https://gceasy.io,可以使用谷歌或者github账号进行登录,GCeasy 是一个基于 Web 的垃圾回收日志分析工具,可以用于分析 JVM 的垃圾回收日志,提供可视化的分析结果和建议。GCeasy 可以分析所有主流的垃圾回收器,包括 CMS、G1、Parallel 和 Serial 等,支持多种垃圾回收日志格式,包括 GC log、Jstat log 和 JMX 等。
我们在项目启动时,开启GC日志打印,-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/tmp/gc.log,或者使用文章开头的启动参数,就可以获取到GC的日志,然后拿到GC日志之后,在https://gceasy.io导入日志文件:
在这里插入图片描述
稍等一会就可看到分析结果了,这个结果的可视化做的很好,但是注意个人用户一个账号一个月只能免费用5次哈,理论上足够的,实在不行谷歌登录用5次,github登录再用5次,一共10次怎么也够用了。。。然后看分析结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个分析结果中有很多有用的信息,这里就不展开讲了,感兴趣的可以专门去查阅一下分析结果的含义,网上挺多资料的,总之这个分析结果对GC优化很有帮助,而且能生成图表,还能下载成pdf,装逼神器啊!!!。。。给不懂技术的老板看,一看就很高大上有木有?

到这里其实工具介绍的差不多了,问题的解决方案其实应该已经有一个大致的方向和思路了,如果到这里还没有思路,那就说明对Jvm、GC等还没有深刻的认知,你要会用这些工具可不够,还要会看着工具给出的信息分析出

三. OOM了怎么办

待补充…

四. CPU告警怎么办

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyQt qrc2py 使用PowerShell将qrc文件转为py文件并且将导入模块PyQt或PySide转换为qtpy模块开箱即用

前言 由于需要使用不同的qt环境&#xff08;PySide&#xff0c;PyQt&#xff09;所以写了这个脚本&#xff0c;使用找到的随便一个rcc命令去转换qrc文件&#xff0c;然后将导入模块换成qtpy这个通用库(支持pyside2-6&#xff0c;pyqt5-6)&#xff0c;老版本的是Qt.py(支持pysi…

力扣Lc26--- 1108. IP 地址无效化(java版)-2024年4月02日

1.题目描述 2.知识点 注1&#xff1a;首先&#xff0c;在Java中&#xff0c;字符类型应该使用单引号’&#xff0c;而不是双引号"。其次&#xff0c;修改字符数组中的元素应该使用单引号。 注2&#xff1a;String类的replace方法用于在字符串中替换指定的字符或字符序列。…

OpenHarmony实战:RK3568 开发板镜像烧录指南

前言 烧录开发板是每个开发者的必修课&#xff0c;每次对系统的修改务必进行烧录测试&#xff0c;确保修改正确和不会引入新问题。 本文基于 Windows10&#xff0c;以 RK3568 开发板为例&#xff0c;指导如何烧录 OpenHarmony 镜像&#xff0c;镜像也叫固件。Hihoop&#xff…

芒果YOLOv5改进89:卷积SPConv篇,即插即用,去除特征图中的冗余,FLOPs 和参数急剧下降,提升小目标检测

芒果专栏 基于 SPConv 的改进结构,改进源码教程 | 详情如下🥇 👉1. SPConv 结构、👉2. CfSPConv 结构 💡本博客 改进源代码改进 适用于 YOLOv5 按步骤操作运行改进后的代码即可 即插即用 结构。博客 包括改进所需的 核心结构代码 文件 YOLOv5改进专栏完整目录链接:…

day10 类的构造器 权限修饰符

目录 构造器 类的成员之构造器 调用其他构造器 idea构造器创建快捷方式 权限修饰符 构造器 类的成员之构造器 类的成员-属性 &#xff1a;用来对对象进行说明&#xff08;保存对象的状态&#xff09; 类的成员-方法 &#xff1a;用来实现具体的功能 类的成员-构造器 &…

Docker部署Nexus Maven私服并且实现远程访问Nexus界面

目录 ⛳️推荐 1. Docker安装Nexus 2. 本地访问Nexus 3. Linux安装Cpolar 4. 配置Nexus界面公网地址 5. 远程访问 Nexus界面 6. 固定Nexus公网地址 7. 固定地址访问Nexus ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&am…

毕马威:《智慧之眼:开启汽车感知新时代》

在全球科技飞速发展和产业革新的大潮中&#xff0c;汽车产业正在以前所未有的速度向网联化、智能化的方向转型。汽车传感器作为智能联网汽车发展的关键环节之一&#xff0c;扮演着举足轻重的角色。 毕马威一直关注汽车产业的变化与发展&#xff0c;为了更好地为汽车行业赋能&a…

基于vue实现动态table

1、代码 <div style"height: 600px; overflow: scroll;"> <!-- height: 600px; overflow: scroll;作用是超出页面可以滑动 --><div ng-repeat"row in entity.procedureList"><cb-title title"工序{{row.procedireLocation}}&quo…

空窗期并非求职大忌!测试人这么回答轻松拿到offer!

为啥今天想起这个话题呢&#xff0c;因为我之前有过这样的经历&#xff0c;且身边的小伙伴也频频遇到面试官来这么个灵魂拷问&#xff0c;所以觉得这点其实还挺重要的&#xff0c;特来分享一下我的应对之策。 既然问题出来了&#xff0c;我们就要弄懂它的来龙去脉&#xff0c;…

[mmu/cache]-ARM MMU的学习笔记-一篇就够了

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; ARMV8-aarch64的MMU 1、MMU概念介绍 MMU分为两个部分: TLB maintenance 和 address translation MMU的作用&#xff0c;主要是完成地址的翻译&#xff0c;无论是main-memory地…

Node.js-知识点学习总结归纳

Node.js-知识点学习总结归纳 安装nodenode运行方式通过Node.js直接运行js文件&#xff08;也就不用通过网页html了&#xff09;绝对路径调用:相对路径调用&#xff1a;直接运行js命令&#xff1a; Vscode控制台使用node运行js文件 安装node 这个就不用讲了吧&#xff0c;网上搜…

mac mini m1芯片 Xcode 15.3 各种报错的问题

错误一&#xff1a; /Users/mac/Desktop/Test_project/mobile-ios/Test/Test-Bridging-Header.h:4:9 failed to emit precompiled header /Users/mac/Library/Developer/Xcode/DerivedData/App-apvcgkuclncgfqdlzqcoffyaexos/Build/Intermediates.noindex/PrecompiledHeaders/…

[Linux]基础IO(上)--理解文件系统调用、文件描述符、万物皆文件

一、文件的理解 每种语言都有进行文件操作的函数接口&#xff0c;例如C语言的fopen、fwrite、fprintf等等&#xff0c;但是进行文件操作的前提是代码已经跑起来&#xff0c;因为文件的打开与关闭要通过CPU来运行程序代码&#xff0c;所以打开文件的本质是进程打开文件&#xff…

day01 51单片机

51单片机学习 1 51单片机概述 1.1 51单片机简介 目前使用的51单片机一般是宏晶STC89系列,这其中流传最广的版本,也是我们课程的主角,就是STC89C52RC。 1.2 命名规则 1.3 单片机最小应用系统 2 点亮LED灯 2.1 硬件原理图 这个原理图非常简单,VCC接保护电阻R1,串联LED1最…

企业周年庆3d云展厅促进了客企间交流与互动

在数字化浪潮席卷而来的今天&#xff0c;传统的展示方式已难以满足现代人对信息获取与体验的高标准需求。为此&#xff0c;一种革命性的展示方式——线上3D虚拟展厅应运而生&#xff0c;以其独特的魅力逐渐引领展示方式的革新。 线上3D虚拟展厅开发&#xff0c;不仅为参与者带来…

突破编程_前端_JS编程实例(分割窗体组件)

1 开发目标 分隔窗体组件旨在提供灵活的窗体分隔功能&#xff0c;支持横向分割与纵向分隔两种类型&#xff0c;并具备拖拽调整窗体比例的功能&#xff0c;同时提供最小比例设置&#xff0c;以防止窗体被过度缩小&#xff1a; 2 详细需求 2.1 分隔窗体类型 &#xff08;1&…

软件工程学习笔记14——案例解析篇

案例解析篇 一、大型开源项目对软件工程的应用1、开发迭代过程 二、大厂是怎样应用软件工程的1、软件项目开发团队组成&#xff08;1&#xff09;软件开发团队规模小&#xff08;2&#xff09;没有专职测试&#xff08;3&#xff09;DevOps 文化 2、开发工具的使用3、项目开发流…

结构体,联合体,枚举( 2 )

目录 2.联合体 2.1联合体类型的声明 2.2联合体的特点 2.3联合体的内存大小 3.枚举 3.1枚举类型的声明 3.2枚举类型的优点 3.3枚举类型的使用 2.联合体 联合体&#xff08;Union&#xff09;是另一种复合数据类型&#xff0c;它允许我们在同一内存位置存储不同的数据类型…

PyYAML,一个强大的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个强大的 Python 库 - pyyaml。 Github地址&#xff1a;https://github.com/yaml/pyyaml/ 在处理配置文件、序列化数据等场景中&#xff0c;YAML&#xff08;YAML Ain’t Ma…

雷勒过滤与您相约2024第13届生物发酵展

参展企业介绍 青岛雷勒过滤科技有限公司是一家致力于不锈钢过滤网&#xff0c;涂料筛&#xff0c;滤袋等研发、生产和服务一体的综合型公司。雷勒专业生产各种高品质的不锈钢过滤元件&#xff0c;用于各种关键的过滤与分离环节。 雷勒拥有先进的生产设备&#xff0c;完善的产…