当前位置: 首页 > news >正文

Linux上快速定位Java代码问题行

生产环境中,经常会遇到CPU持续飙高或内存、IO飙高,如何快速定位问题点是很多新手头疼的问题,只能通过经验和代码推理,其实这里针对Java程序可以通过top和jstack命令,快速定位到问题代码。

Top命令的输出

具体定位之前,先补全一下top命令的输出解释,top 命令的输出是动态更新的,通常每3秒刷新一次,但这个刷新频率可以通过交互命令 d 来调整。看一个top命令的输出样例:

top - 16:45:26 up 5 days,  3:12,  1 user,  load average: 0.00, 0.01, 0.05
Tasks: 239 total,   1 running, 238 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.0 us,  0.6 sy,  0.0 ni, 98.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  16280104 total,  10346652 free,   2689256 used,   3256196 buff/cache
KiB Swap:   2097148 total,   2097148 free,        0 used.   7256332 avail MemPID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND      1234 user1     20   0 12345672 1048576  524288 S  0.7  6.4   2:34.16 java     1 root      20   0       0      0      0 S  0.0  0.0   0:03.16 init      72 www-data  20   0  344736   8192   7168 S  0.3  0.1   0:01.93 apache2     

top 命令的输出分为两部分:顶部的系统概览和底部的进程列表。

顶部的系统概览

  • 任务:显示系统中的进程总数,以及运行(R)、休眠(S)、停止(T)、僵尸(Z)状态的进程数量。
  • %Cpu(s):CPU使用率的百分比,通常分为用户空间(us)、系统空间(sy)、空闲(id)、等待I/O(wa)和其他(hi、si、st)。
  • KiB Mem:系统内存的使用情况,包括已使用(used)、空闲(free)、缓存(buffers/cached)和可用内存(available)。
  • KiB Swap:交换空间的使用情况,包括已使用(used)和空闲(free)。
  • 时间:显示当前时间、系统运行时间、平均负载(1分钟、5分钟、15分钟)。

底部的进程列表

  • PID:进程ID。
  • USER:进程所有者的用户名称。
  • PR:进程的优先级(数值越小,优先级越高)。
  • NI:进程的nice值(影响进程的优先级)。
  • VIRT:虚拟内存的大小,单位通常是KiB。
  • RES:常驻内存的大小,即进程实际占用的物理内存,单位通常是KiB。
  • SHR:共享内存的大小,单位通常是KiB。
  • S:进程的状态,如休眠(S)、运行(R)、停止(T)等。
  • %CPU:进程占用的CPU使用率百分比。
  • %MEM:进程占用的内存使用率百分比。
  • TIME+:进程占用CPU的总时间。
  • COMMAND:启动进程的命令名称或命令行。

在这个示例中,系统已经运行了5天3小时12分钟,平均负载在过去1分钟是0.00,过去5分钟是0.01,过去15分钟是0.05。CPU使用情况显示1%的用户空间使用率和0.6%的系统空间使用率,其余为空闲。内存方面,总共有16280104KiB的内存,其中10346652KiB是空闲的,2689256KiB被使用,3256196KiB作为缓存或缓冲。交换空间总共有2097148KiB,全部空闲。

进程列表显示了PID为1234的进程占用了较多的CPU和内存资源,它是以用户 user1 运行的,它是一个Java程序。

快读定位源代码步骤

通过top可以快速定位到资源利用异常的进程程序,这时候,如果是我们开发的Java程序占用较高的资源,但是又无法确认是具体哪一部分占用时,则可以通过 top命令和jstack进行具体代码的定位。思路如下:

首先,使用Top命令,发现存在问题的进程:

top - 10:05:00 up 3 days,  5:25,  1 user,  load average: 0.10, 0.15, 0.20
Tasks: 242 total,   2 running, 240 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5.0 us,  1.0 sy,  0.0 ni, 94.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16384M total,  8192M used,   8192M free,   2048M buff/cache
KiB Swap:  4096M total,     0M used,  4096M free.   4096M avail Mem PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM   TIME+ COMMAND      
23456 root     20   0 21G 15G  1024K S  0.5 91.5   1:50.01 java 
73455 root     20   0 0.2G 0.1G  1024K S  0.5 91.5   00:34.01 mysqld
11234 root     20   0 0.1G 0.15G 1024K S  0.5 91.5   1:45.03 sh

在这个例子中,PID为23456的 Java 进程使用了超过15GB的物理内存,并且占用了91.5%的内存资源。这可能意味着它正在消耗大量内存,可能会导致内存泄漏或其他内存使用问题。 

使用Top查看进程里的线程

获得了具体的问题进程后,通过 top -Hp [PID] 来查看其内部线程

top -Hp 23456top - 10:15:00 up 3 days,  5:35,  1 user,  load average: 0.50, 0.40, 0.30
Tasks: 500 total,   2 running, 498 sleeping,   0 stopped,   0 zombie
%Cpu(s): 10.0 us,  2.0 sy,  0.0 ni, 88.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16384M total,  9000M used,  7384M free,   2048M buff/cache
KiB Swap:  4096M total,     0M used,  4096M free.   7384M avail MemPID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND      23457 root     20   0 21G 15G 1024K S  5.0 91.5   1:50.01 java        23457 root     20   0  4G 3.5G  8192K R 10.0  2.1   0:05.20 java        23458 root     20   0  4G 3.5G  8192K S  3.0  2.1   0:04.30 java        23459 root     20   0  4G 3.5G  8192K S  2.0  2.1   0:03.40 java        

将线程ID转为16进制

找到对应异常的线程,使用16进制转换命令 printf "0x%x" [线程ID],获取其线程16进制编码

[root@10]# printf "0x%x" 23457
0x5ba1[root@10]#

jstack跟踪堆栈定位代码

拿到了线程16进制编码,则通过java工具内置的jstack命令进行代码定位:

jstack [PID] | grep [线程16进制编码] -A 5

# 数字5表示输出栈顶最前几行代码

jstack 23456 | grep 0x5ba1 -A 5"Thread-3" #23458 prio=5 os_prio=31 cpu=33.42ms elapsed=6.25s tid=0x5BEA runnablejava.lang.Thread.State: RUNNABLEat java.util.HashMap.get(HashMap.java:628)at com.example.MyApplication.doSomething(MyApplication.java:42)at com.example.MyApplication.access$000(MyApplication.java:18)at com.example.MyApplication$1.run(MyApplication.java:77)at java.lang.Thread.run(Thread.java:748)

相关文章:

  • 云桌面运维工程师
  • 大数据------JavaWeb------JSP(完整知识点汇总)
  • Spring Boot中的安全漏洞防护
  • Django靓号管理系统:实现用户列表功能
  • react 重新加载子组件
  • 目标检测入门:3.目标检测损失函数(IOU、GIOU、GIOU)
  • 【ubuntu】切换shell并显示git分支名字
  • Python学习笔记28:进阶篇(十七)常见标准库使用之质量控制中的代码质量与风格第二部分
  • 笔记-linux写文件的方法
  • 【FFmpeg】avcodec_open2函数
  • tls各个版本的安全性介绍
  • Appium启动APP时报错Security exception: Permission Denial
  • 高级Redis之Stream的用法示例
  • 同时在一台服务器上使用Java 8和Java 17的技术指南
  • Java基础(基于韩顺平老师的笔记)
  • JavaScript-如何实现克隆(clone)函数
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 2017届校招提前批面试回顾
  • Android组件 - 收藏集 - 掘金
  • DataBase in Android
  • flutter的key在widget list的作用以及必要性
  • Java Agent 学习笔记
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • PaddlePaddle-GitHub的正确打开姿势
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Redux 中间件分析
  • Spark学习笔记之相关记录
  • SpringBoot几种定时任务的实现方式
  • 测试开发系类之接口自动化测试
  • 搭建gitbook 和 访问权限认证
  • 来,膜拜下android roadmap,强大的执行力
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • ​马来语翻译中文去哪比较好?
  • ​水经微图Web1.5.0版即将上线
  • (9)STL算法之逆转旋转
  • (C#)获取字符编码的类
  • (C)一些题4
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (四)opengl函数加载和错误处理
  • (转载)深入super,看Python如何解决钻石继承难题
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .net对接阿里云CSB服务
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .net解析传过来的xml_DOM4J解析XML文件
  • .net流程开发平台的一些难点(1)
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • @拔赤:Web前端开发十日谈