详解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应用程序的。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

政安晨:【深度学习神经网络基础】(一)—— 逐本溯源

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 与计算机一样的古老历史 神经网络的出现可追溯到20世纪40年…

LeetCode101:对称二叉树

题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 代码 递归 class Solution { public:bool compare(TreeNode* left, TreeNode* right) {if (left nullptr && right ! nullptr) return false;else if (left ! nullptr && right nul…

基于Matlab的血管图像增强算法,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

学习鸿蒙基础(9)

目录 一、鸿蒙国际化配置 二、鸿蒙常用组件介绍 三、鸿蒙像素单位介绍 四、鸿蒙布局介绍 1、Row与Column线性布局 2、层叠布局-Stack 3、弹性布局 4、栅格布局 5、网格布局 一、鸿蒙国际化配置 base目录下为默认的string。en_US对应美国的。zh_CN对应中国的。新增一个s…

ActiveMQ Artemis 系列| High Availability 主备模式(消息复制) 版本2.19.1

一、ActiveMQ Artemis 介绍 Apache ActiveMQ Artemis 是一个高性能的开源消息代理&#xff0c;它完全符合 Java Message Service (JMS) 2.0 规范&#xff0c;并支持多种通信协议&#xff0c;包括 AMQP、MQTT、STOMP 和 OpenWire 等。ActiveMQ Artemis 由 Apache Software Foun…

小白从0学习ctf(web安全)

文章目录 前言一、baby lfi&#xff08;bugku-CTF&#xff09;1、简介2、解题思路1、解题前置知识点2、漏洞利用 二、baby lfi 2&#xff08;bugku-CTF&#xff09;1.解题思路1、漏洞利用 三、lfi&#xff08;bugku CTF&#xff09;1、解题思路1、漏洞利用 总结 前言 此文章是…

瓷砖通铺选择亮面还是哑光?了解这6点不难选。福州中宅装饰,福州装修

选择瓷砖通铺亮面还是哑光&#xff0c;可以从多个角度来考虑&#xff1a; ①空间感觉 亮面瓷砖通常会使空间看起来更加宽敞和明亮&#xff0c;而哑光瓷砖则给人大气、稳重的感觉。如果希望让空间显得更加宽敞&#xff0c;亮面瓷砖是一个不错的选择。 ②清洁与维护 亮面瓷砖更…

云电脑安全性怎么样?企业如何选择安全的云电脑

云电脑在保障企业数字资产安全方面&#xff0c;采取了一系列严谨而全面的措施。随着企业对于数字化转型的深入推进&#xff0c;数字资产的安全问题日益凸显&#xff0c;而云电脑作为一种新兴的办公模式&#xff0c;正是为解决这一问题而生。云电脑安全吗&#xff1f;可以放心使…

React系列之合成事件与事件处理机制

文章目录 React事件处理机制原生事件的事件机制事件代理&#xff08;事件委托&#xff09; 合成事件使用合成事件目的合成事件原生事件区别事件池 原生事件和React事件的执行顺序e.stopPropagation() React17事件机制的修改 React事件处理机制 react 事件机制基本理解&#xf…

C++ :STL中deque的原理

deque的结构类似于哈希表&#xff0c;使用一个指针数组存储固定大小的数组首地址&#xff0c;当数据分布不均匀时将指针数组内的数据进行偏移&#xff0c;桶不够用的时候会像vector一样扩容然后将之前数组中存储的指针拷贝过来&#xff0c;从原理可以看出deque的性能是非常高的…

docker部署-RabbitMq

1. 参考 RabbitMq官网 docker官网 2. 拉取镜像 这里改为自己需要的版本即可&#xff0c;下面容器也需要同理修改 docker pull rabbitmq:3.12-management3. 运行容器 docker run \ --namemy-rabbitmq-01 \ -p 5672:5672 \ -p 15672:15672 \ -d \ --restart always \ -…

java入门学习Day01

本篇文章主要是学会如何使用IDEA&#xff0c;和运行第一个java文件。 java环境安装&#xff1a;Windows下Java环境配置教程_windows java环境配置-CSDN博客 IDEA安装&#xff1a;IDEA 2023.2.5 最新激活码,注册码&#xff08;亲测好用&#xff09; - 异常教程 以上两个链接…

C++—vector的介绍及使用 vector的模拟实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.4 vecto…

JVM 八股(一)

JVM 1.类装载的执行过程 加载&#xff1a; 元空间存储构造函数&#xff0c;方法&#xff0c;字段等 验证 准备 解析 初始化 使用 2.垃圾回收 什么是垃圾回收&#xff1f;怎样找到这些垃圾&#xff1f;找到垃圾后是怎么清除的&#xff08;垃圾回收算法&#xff09;&#x…

一篇搞定AVL树+旋转【附图详解旋转思想】

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

【C语言】贪吃蛇【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 一、游戏说明&#xff1a; 一个基于C语言链表开发的贪吃蛇游戏&#xff1a; 1. 按方向键上下左右&#xff0c;可以实现蛇移动方向的改变。 2. 短时间长按方向键上下左右其中之一&#xff0c;可实现蛇向该方向的短时间…

智能指针(C++11)

智能指针的使用 问题 我们在平时写程序的时候&#xff0c;有些情况下不可避免地会遇见内存泄露的情况。内存泄露是指因为疏忽或错误&#xff0c;造成程序未能释放已经不再使用的内存的情况。例如下面这个例子&#xff0c;内存泄漏不易被察觉。 int div() {int a, b;cin >…

【复习linux相关命令】

查看命令位置&#xff0c;查找命令 which命令 查看命令的位置 [rootVM-12-15-opencloudos ~]# which cd /usr/bin/cd [rootVM-12-15-opencloudos ~]# which java /usr/local/java/jdk1.8.0_261/bin/java [rootVM-12-15-opencloudos ~]# which pwd /usr/bin/pwdfind查找文件 …

element+Vue2,在一个页面跳转到另一个页面,并自动选中table的某一行

需求&#xff1a;点击A页面的某处&#xff0c;跳转到B页面并选中B页面表格的某一行&#xff08;点击B页面的搜索后需要清空默认选择的状态&#xff09;环境&#xff1a;vue2、element的table&#xff0c;table允许多选知识点&#xff1a;主要使用到table的这两属性&#xff1a;…

Diffusion添加噪声noise的方式有哪些?怎么向图像中添加噪声?

添加噪声的方式大致分为两种&#xff0c;一种是每张图像在任意timestep都加入一样的均匀噪声&#xff0c;另一种是按照timestep添加不同程度的噪声 一、在任意timestep都加入一样的noise batch_size 32x_start torch.rand(batch_size,3,256,256) noise torch.randn_like(x_…