详解JAVA程序调优

目录

1.概述

2.命令

2.1.查看JAVA进程

2.2.查看虚拟机状态

2.3.查看线程的情况

3.工具

3.1.jconsole

3.2.jvisualVM

4.实战场景


1.概述

在实际工作中我们难免会遇见程序执行慢、线程死锁等一系列的问题,这时候就需要我们定位具体问题然后来解决问题了。所谓的程序调优其实也就是定位问题然后解决问题。怎么定位问题喃?在JAVA程序的调优中我们无非要关注以下内容:

  • JVM的情况

  • 程序的情况

JVM的情况无其实就是去看一下它的类加载情况、内存使用情况、GC的情况。

程序的情况无非就是其线程的运行情况。

JDK为我们提供了两套方案来查看这两方面的情况,一方面是命令,另一方面是工具。

2.命令

2.1.查看JAVA进程

当然查看上面说的两方面情况的前提是要知道程序的进程是哪个对吧。所以首先是第一个常用的命令:

  • jps,查看当前机器上的java进程

jps命令默认输出进程的ID号以及对应的主启动类:

jps常用的一些参数:

  • -q:简洁模式,只输出Java虚拟机(JVM)的进程ID(PID),不显示主类名称或者其他详细信息。

  • -m:输出运行主类(即包含main方法的类)时传递给main方法的参数。

2.2.查看虚拟机状态

jstat,查看虚拟机状态,该命令需要跟上参数来指定具体查看的项目。

jstat的主要常用参数如下:

  • 监控堆内存(Heap): jstat -gc <pid> [interval] [count]:显示GC(Garbage Collection)统计信息,包括各代堆内存的大小、已用空间、已分配对象数以及GC次数与时间等。这里要注意的是如果只是想看内存情况,jmp命令也可以办到。

  • 类装载系统(Class Loader): jstat -class <pid>:显示类加载器相关的统计信息,比如已加载的类数量及其占用的空间。

  • 线程信息(Thread Information): jstat -thread <pid>:显示有关Java线程的信息,如活动线程数、死锁检测等。

  • GC算法详细信息(Detailed GC Algorithm Info): jstat -gccapacity <pid>:显示各个分代区域的容量配置。 jstat -gcutil <pid>:提供更详细的GC使用率信息,包括堆区的使用率和永久代的使用情况。

jstat -gc的结果对应的字段含义如下:

  • 年轻代相关指标: S0C: 第一个幸存区(Survivor Space 0)的当前容量(字节)。 S1C: 第二个幸存区(Survivor Space 1)的当前容量。 S0U: 第一个幸存区当前已使用的空间。 S1U: 第二个幸存区当前已使用的空间。

  • Eden区和老年代相关指标: EC: Eden区的当前容量。 EU: Eden区当前已使用的空间。 OC: 老年代(Old Generation)的当前容量。 OU: 老年代当前已使用的空间。

  • 元空间(Metaspace)或永久代(Permanent Generation,在JDK 1.8之前的版本中): MC: 元空间的当前容量(在JDK 1.8及更高版本中)或永久代的当前容量(在JDK 1.8之前)。 MU: 元空间当前已使用的空间或永久代当前已使用的空间。

  • 垃圾收集次数和时间: YGCT: 自JVM启动以来,年轻代垃圾回收(Young Generation Collection)所花费的总时间。 FGCT: 自JVM启动以来,全局或全堆垃圾回收(Full Garbage Collection,也可能是并发标记清除等类型的GC)所花费的总时间。 GCT: 总共的垃圾回收时间(YGCT + FGCT)。

jstat -gccapacity 结果对应的字段含义如下:

  • NGCMN - 新生代(Young Generation)的最小容量。

  • NGCMX - 新生代的最大容量。

  • NGC - 当前新生代的实际容量。

  • OGCMN - 老年代(Old Generation)的最小容量。

  • OGCMX - 老年代的最大容量。

  • OGC - 当前老年代的实际容量。

  • PC/MC - 元空间(MetaSpace)的最小容量(在JDK 1.8及更高版本中)。在JDK 1.8之前,这里是永久代(PermGen)的相关字段。

  • PC/MC - 元空间的当前容量。

  • CCSMN - 如果存在的话,表示压缩类空间(Compressed Class Space)的最小容量(在启用压缩类空间的情况下)。

  • CCSMX - 压缩类空间的最大容量。

  • CCSC - 当前压缩类空间的实际容量。

  • OC (Old Capacity): 表示当前老年代(Old Generation)的容量,即当前老年代能容纳多少内存空间。

  • MCMN (Metaspace Capacity Minimum): 在JDK 1.8及更高版本中,这个字段指的是元空间(Metaspace)的最小容量。元空间取代了永久代(PermGen),用于存储类元数据和静态变量等。

  • MCMX (Metaspace Capacity Maximum): 表示元空间的最大容量,即元空间允许增长到的最大内存大小。

  • MC (Metaspace Capacity): 表示当前元空间的实际容量,即当前元空间占用的内存大小。

jstat -gcutil 结果对应的字段含义如下:

  • S0:第一个幸存区(Survivor Space 0)的使用率。

  • S1:第二个幸存区(Survivor Space 1)的使用率。

  • E:伊甸园区(Eden Space)的使用率。

  • O:老年代(Old Generation)的使用率。

  • M:元空间(Metaspace)的使用率。在JDK 1.8及更高版本中,元空间取代了永久代(PermGen)来存储类的元数据和静态变量。

  • CCS(如果存在):压缩类空间(Compressed Class Space)的使用率(在启用压缩类空间的情况下)。

  • YGC:自JVM启动以来,年轻代(Young Generation)垃圾回收的次数。

  • YGCT:自JVM启动以来,年轻代垃圾回收所消耗的总时间。

  • FGC:自JVM启动以来,全局或全堆(Full GC)垃圾回收的次数。

  • FGCT:自JVM启动以来,全局或全堆垃圾回收所消耗的总时间。

  • GCT:自JVM启动以来,所有垃圾回收(包括年轻代和全局)所消耗的总时间。

2.3.查看线程的情况

查看线程的情况无非就是抓一下线程的执行记录,也就是线程快照,jstack,可以用来抓线程快照,从而展示JVM当前线程的一个总体情况。

如果Java进程启用了远程调试,jstack可以连接到远程主机上的调试端口来获取线程堆栈信息:

jstack [-l] <host>:<port>

其中,-l 参数会包含锁定信息,有助于发现死锁问题。

jstack命令输出的信息通常包括:

  • 线程ID(Thread ID)和线程名称(Thread Name)

  • 线程的状态(如RUNNABLE、BLOCKED、WAITING、TIMED_WAITING)

  • 线程执行的Java方法堆栈(Method Stack Trace),按照调用顺序逐层显示,这有助于追踪线程执行流和识别阻塞点。

通过分析jstack命令的输出,可以快速找到哪些线程处于何种状态,以及可能导致性能瓶颈或问题的代码位置,从而指导进一步的问题排查和性能调优工作。

3.工具

3.1.jconsole

连接上我们想监控的程序就可以看到,这其实就是个集成了前文所有命令的功能的图形化界面:

这里需要注意的是jconsole可以用来监控MBean,也就是用JMX自行实现的监控指标,对JMX不了解但是有兴趣的读者可以移步:

3.2.jvisualVM

jvisualVM其实和jconsole在功能上大部分是重叠的也是那些命令的图形化工具:

但是其和jconsole不同的是:

当我们用到了JMX,有自定义的MBean的时候一般用jconsole来进行可视化监控。当我们需要导入线程快照的时候一般用jvisualVM。

为什么会导入jvisualVM喃?是因为在实际的生产环境中,为了防止被攻击,服务器不会开出去太多的端口,所以想通过JDK的监控工具直接远程到服务器上去其实是比较难的,所以一般是用jstack命令去抓一段线程快照,然后拉到本地来用jvisualVM来进行可视化分析从而定位问题。

4.实战场景

下面是一些使用上述JDK工具进行具体场景优化和问题排查的例子:

示例1:使用jps和jstat排查内存泄漏

场景:一个长期运行的Java服务突然出现内存占用过高,疑似存在内存泄漏。

操作: 首先,使用jps命令找到目标Java进程的ID。 接着,利用jstat -gcutil <pid>周期性地监控JVM的内存使用情况,包括年轻代、老年代和元空间的使用率,以及垃圾回收的次数和时间。 如果观察到老年代使用率不断攀升且垃圾回收频繁且无效,则可能存在内存泄漏。 进一步,通过jmap -dump:format=b,file=<filename>.hprof <pid>命令生成堆转储文件。 使用MAT(Memory Analyzer Tool)分析堆转储文件,查找是否存在大量未释放的对象及其引用路径。

示例2:使用jstack解决线程死锁问题

场景:一个Java应用在高负载下发生卡顿,初步判断可能是线程死锁。

操作: 使用jps找到目标进程ID。 执行jstack <pid>命令获取线程堆栈信息。 分析输出的线程堆栈,寻找那些状态为BLOCKED并且持有和等待资源相互关联的线程,这些往往是死锁的关键线索。 根据堆栈信息找到造成死锁的代码片段,修改代码以避免死锁发生。

示例3:使用jinfo动态调整JVM参数

场景:一个Java应用在运行时发现GC过于频繁,影响了系统性能。

操作: 使用jps找到目标进程ID。 使用jinfo -flag UseConcMarkSweepGC <pid>检查当前是否使用CMS垃圾收集器。 若确认为CMS,但是效果不佳,可以考虑调整GC参数,如增大初始堆大小 -Xms 或 最大堆大小 -Xmx,或者改变GC策略(如切换到G1垃圾收集器)。 使用jinfo -flag -Xms <new_size> <pid>或jinfo -flag -Xmx <new_size> <pid>动态调整堆大小(并非所有JVM版本都支持所有参数的动态调整)。

示例4:使用jconsole进行实时性能监控

场景:需要持续监控Java应用的CPU、内存、线程数等基础性能指标。

操作: 启动Java应用时添加 -Dcom.sun.management.jmxremote 等JMX远程监控相关参数。 运行jconsole,连接到目标Java应用。 在jconsole界面中,可以实时查看各项性能指标,并进行图表绘制和历史数据分析,快速发现潜在的性能瓶颈。 通过这些实际场景和操作步骤,可以看到JDK自带的各种工具在实际工作中是如何协同配合,帮助我们诊断和优化Java应用程序的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

正弦实时数据库(SinRTDB)的使用(7)-历史统计查询

前文已经将正弦实时数据库的使用进行了介绍&#xff0c;需要了解的可以先看下面的博客&#xff1a; 正弦实时数据库(SinRTDB)的安装 正弦实时数据库(SinRTDB)的使用(1)-使用数据发生器写入数据 正弦实时数据库(SinRTDB)的使用(2)-接入OPC DA的数据 正弦实时数据库(SinRTDB)…

【Frida】【Android】02_JAVA层HOOK

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

从输入url到页面展示的过程

唠唠叨&#xff1a;我不想误人子弟&#xff0c;我这篇算是搬运工&#xff0c;加上自己的理解做点总结&#xff0c;所以还请大家科学上网去看这篇&#xff1a;https://aws.amazon.com/cn/blogs/mobile/what-happens-when-you-type-a-url-into-your-browser/ 是这六个步骤&#…

前端学习<二>CSS基础——13-CSS3属性:Flex布局图文详解

前言 CSS3中的 flex 属性&#xff0c;在布局方面做了非常大的改进&#xff0c;使得我们对多个元素之间的布局排列变得十分灵活&#xff0c;适应性非常强。其强大的伸缩性和自适应性&#xff0c;在网页开中可以发挥极大的作用。 flex 初体验 我们先来看看下面这个最简单的布局…

笔记: JavaSE day16笔记 - string字符串

第十六天课堂笔记 学习任务 Comparable接口★★★★ 接口 : 功能的封装 > 一组操作规范 一个抽象方法 -> 某一个功能的封装多个抽象方法 -> 一组操作规范 接口与抽象类的区别 1本质不同 接口是功能的封装 , 具有什么功能 > 对象能干什么抽象类是事物本质的抽象 &…

学习刷题-14

3.29 贪心算法 跳跃游戏 II 给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 贪心的思路&#xff0c;局部最优&#xff1a;当前可移动距离尽可能多…

Redis 常见数据结构及命令

目录 一.Redis常见的数据结构 二.Redis数据结构对应的命令 1.String类型 2.Hash类型 3.List类型 4.Set类型 5.Sorted Set类型 一.Redis常见的数据结构 Redis支持多种数据结构&#xff0c;包括字符串&#xff08;string&#xff09;、哈希&#xff08;hash&#xff09;、…

B端:甲方吐槽界面丑,少反驳,气势能得100分,体验永远0分

2023-10-24 10:20贝格前端工场 甲方吐槽B端系统界面丑陋时&#xff0c;作为设计师或开发者&#xff0c;我们不应该立即反驳或争辩。相反&#xff0c;我们应该以积极的态度倾听甲方的意见&#xff0c;并采取以下措施&#xff1a; 理解甲方需求&#xff1a; 首先要理解甲方对界…

二维码门楼牌管理应用平台建设:一扫即知,智慧生活新篇章

文章目录 前言一、二维码门楼牌管理的创新之处二、二维码门楼牌管理应用平台的实际应用三、二维码门楼牌管理应用平台的未来展望 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台应运而生&#xff0c;为城市管理和居民生活带来了极大的便利。只需轻轻一扫&a…

CentOS7 磁盘相关的命令及磁盘重新调整分配

umount 在CentOS 7中&#xff0c;umount是一个常用的命令&#xff0c;用于卸载文件系统。以下是一些常用的umount命令&#xff1a; 卸载指定的文件系统&#xff1a; umount /dev/sdXN 其中&#xff0c;/dev/sdXN是你想要卸载的分区。例如&#xff0c;/dev/sda1。 卸载并…

传参的指针,你的值到底变了没?!(有关函数形参修改的另类案例)

我们都知道&#xff0c;想要在函数中修改某个变量的值&#xff0c;传变量本身是没有用的。原因在于不同的函数在不同的空间上&#xff0c;函数的生命周期随着函数的调用而结束&#xff0c;因此在函数内部进行的值操作是不会对函数外的变量产生影响的。所以在函数里面想要修改变…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 3月31日,星期日

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年3月31日 星期日 农历二月廿二 1、 医保局&#xff1a;北京、广西、内蒙古、甘肃已将辅助生殖纳入医保报销。 2、 百日咳卷土重来&#xff0c;今年已有13人死亡&#xff0c;医生提醒&#xff1a;久咳不愈要警惕。 3、 上海…

亚马逊云科技—云从业者认证考试限时 50% 折扣优惠 限量提供, 先到先得!

亚马逊云科技云从业者认证&#xff08;AWS Certified Cloud Practitioner&#xff09;作为全球热门的云基础认证, 对于寻求基础云知识的开发者、专业人士、学生, 以及没有技术背景的职场人士来说, 都是进阶亚马逊云认证之旅的良好起点并助您进一步提升职场竞争力&#xff01; 与…

Spring IoCDI(3)

DI详解 接下来学习一下依赖注入DI的细节. 依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了Autowired这个注解, 完成了依赖注入这个操作. 简单来说, 就是把对象取出来放到某个类的属性中. 在一些文章中…

上市公司-劳动投资效率数据集-Abresid 含原始数据及处理代码(2020-2022年)

01、数据简介 劳动投资效率是指企业在进行劳动力投资时所获得的效益程度。简单来说&#xff0c;它衡量了企业对于人力资源的投入与产出之间的比率&#xff0c;反映了企业在人力资源管理方面的效果和效率。 Abresid是劳动投资效率的测度指标&#xff0c;它来源于某个回归模型的…

Vmware下减小Ubuntu系统占用系统盘大小

1、虚拟机设置下占用空间 如图&#xff0c;给虚拟机分配了120GB&#xff0c;已经占用116.9GB&#xff0c;开机会提示空间不足。 2、实际使用空间 ubuntu系统下使用“df -h”命令查看实际使用空间大小50GB左右 造成这个原因是&#xff0c;虚拟机的bug&#xff1a;在虚拟机的ub…

【PHP编程使用UI框架】——GET和POST的请求方法

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

详解 Java多线程带来的的风险-线程安全

目录 一、什么是线程安全&#xff1f; 二、线程不安全的原因 1、线程调度是随机的 2、修改共享数据&#xff1a;多个线程修改同⼀个变量 3、原⼦性 ​编辑 &#xff08;1&#xff09;什么是原⼦性 &#xff08;2&#xff09;⼀条 java 语句不⼀定是原⼦的&#xff0c;也不⼀定…

【转移表】

文章目录 一、函数指针数组1.什么事函数指针数组2.函数指针数组如何定义 二、转移表结束语 一、函数指针数组 1.什么事函数指针数组 在我们学习函数指针数组前&#xff0c;大家可以一起回顾一下我们以前学习的指针和数组。 数组指针 数组指针是指指向数组的指针。 int arr…

每日五道java面试题之springboot篇(四)

目录&#xff1a; 第一题. Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?第二题. 微服务中如何实现 session 共享 ?第三题. Spring Boot 中如何实现定时任务 ?第四题. 运行 Spring Boot 有哪几种方式&#xff1f;第五题. 开启 Spring Boot 特性有哪几种方式&#xff1f…