• Dump文件生成,内容,以及分析


    ​​​​​​​本文用到的工具只是简单介绍,让你有个感官认识,重点是核查思路的熟悉

    为啥需要dump内存文件

    服务器CPU,内存占用空间飙升,或者GC频繁,首先需要排除的就是内存泄露,即内存中没有的对象的空间没有被及时回收导致的。而检测内存泄露就需要看哪种类在内存占了较多份额,从而定位到代码,然后修改。


    分析思路

    1. cpu,mem 飙升,确认是否web服务的问题并记录pid

    2. 查看GC情况,如果每次gc效果不明显说明内存泄露

    3. 导出dump,分析。定位占用top n的类

    4. 分析并找到 哪里创建的类占用了大量


    制作dump

    jstack

    打印线程的栈信息,制作线程Dump。

    jstack <进程ID> >> <输出文件>

    jstack 2316 >> c:\thread.txt

    ## Linux下使用Kill命令制作线程Dump,输出线程Dump到目标Java进程的标准输出

    kill -quit <进程ID>

    kill -3 <进程ID>

    jmap

    使用jmap命令制作堆Dump

    # 打印存活的对象大小和个数

    jmap -histo:live

    jmap -histo:live 64421 > live.log

    # 二进制方式存储堆文件

    jmap -dump:format=b,file=文件名.hprof <进程ID>

    以二进制方式生成文件/opt/wkt/wkt1.hprof,进程PID=64421

    jmap -dump:format=b,file=/opt/wkt/wkt1.hprof 64421


    Dump读取前基础铺垫

    Dump文件内容

    制作时间

    Java 版本

    线程信息:名称、优先级、标识、状态、堆栈

    死锁信息:存在直接Java线程的死锁时才包含。

    内存信息:使用kill制作时才包含。

    线程信息

    线程状态

    NEW: 未启动的。不会出现在Dump中。

    RUNNABLE: 在虚拟机内执行的。

    BLOCKED: 受阻塞并等待监视器锁。

    WATING: 无限期等待另一个线程执行特定操作。

    TIMED_WATING: 有时限的等待另一个线程的特定操作。

    TERMINATED: 已退出的。

    监视器(Monitor)

    监视器:对象锁的访问控制结构。也指对象的锁。

    监视器项:线程的代理人。

    进入区:表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则进入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。

    拥有者:表示某一线程成功竞争到对象锁。

    等待区:表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

    调用修饰

    locked <地址> 目标

    waiting to lock <地址> 目标

    waiting on <地址> 目标

    parking to wait for <地址> 目标

    实例锁: (a 类名)——synchronized对象。

    类锁:(a Class for 类名)——静态synchronized方法

    locked:通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。对象锁是可以线程重入的。

    at oracle.jdbc.driver.PhysicalConnection.prepareStatement

    - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)

    at oracle.jdbc.driver.PhysicalConnection.prepareStatement

    - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)

    at com..datasource.PooledConnection.prepareStatement

    synchronized (conn) { // conn的类型是T4CConnection

    // 同步块操作

    }

    waiting to lock:通过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked​​​​​​​​​​​​​​

    at com..impl.CacheHolder.isVisibleIn(CacheHolder.java:165)

    - waiting to lock <0x0000000097ba9aa8> (a CacheHolder)

    at com..impl.CacheGroup$Index.findHolder

    at com..impl.ContextImpl.find

    at com..BaseDataCenter.findInfo

    synchronized (holder) { // holder的类型是CacheHolder

    // 临界区操作

    }

    waiting on:通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进去对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING

    at java.lang.Object.wait(Native Method)

    - waiting on <0x00000000da2defb0> (a WorkingThread)

    at com..WorkingManager.getWorkToDo

    - locked <0x00000000da2defb0> (a WorkingThread)

    at com..WorkingThread.run

    synchronized(thread) {

         // 同步块操作……

         try {

               thread.wait();

         catch(InterruptException e) { /* 中断异常处理 */ }

    }

    parking to wait for

    at sun.misc.Unsafe.park(Native Method)

    - parking to wait for <0x00000000eb8f35c8> (a FutureTask$Sync)

    at java.util.concurrent.locks.LockSupport.park(LockSupport:156)

    ...

    at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock()

    park是基本的线程阻塞原语,不通过监视器在对象上阻塞。

    随concurrent包会出现的新的机制,与synchronized体系不同。

    synchronized模型相关的调用修饰

    1.locked <对象地址> (a 类名)

    使用synchronized申请对象锁成功,监视器的拥有者。

    2. waiting to lock <对象地址> (a 类名)

    使用synchronized申请对象锁未成功,在进入区等待。

    3. waiting on <对象地址> (a 类名)

    使用synchronized申请对象锁成功后,释放锁并在等待区等待

    分析模式

    wait on monitor entry 被阻塞的,肯定有问题

    runnable 注意IO线程

    in Object.wait() 注意非线程池等待

    虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。

    "wss-635" waiting for monitor entry

      java.lang.Thread.State: BLOCKED (on object monitor)

        at com..impl.CacheHolder.isVisibleIn(CacheHolder.java:165)

        - locked <0x0000000097ba9aa8> (a com..CacheHolder)


    分析工具

    jhat

    下载生成dump二进制文件wkt1.hprof,并下载到本地。

    cmd中输入:jhat wkt1.hprof

     访问:http://localhost:7000/

    jvisualvm

    window可视化界面,Ctr+R,CMD,输入jvisualvm回车,打开主界面后,点击【文件】下【装入】

     查看类,可以看到不同类占的内存大小:

    Jvm.分析工具(jps,jmap,jstack,jinfo,jconsole,jvisualvm,arthas,jprofiler,mat)_闲猫的博客-CSDN博客

    MAT

    MAT(MemoryAnalyzerTool)是Eclipse提供的一个内存分析工具,作为Java的内存分析中一个比较好用的工具,掌握MAT的基本用法基本上算是定位问题中一项最重要的基础技能了。

    下载地址:链接:https://pan.baidu.com/s/1Qyy1bJQtosNlJ9VOt9GzVA 提取码:8hgd

    Jvm.分析工具(jps,jmap,jstack,jinfo,jconsole,jvisualvm,arthas,jprofiler,mat)_闲猫的博客-CSDN博客

  • 相关阅读:
    Oracle安全基线检查
    线性代数-知识点复习(面试用)
    软件开发定律:霍夫施塔特定律,为什么项目交付总是会延期?
    文盘Rust -- 生命周期问题引发的 static hashmap 锁 | 京东云技术团队
    源码解读etcd heartbeat,election timeout之间的拉锯
    湖仓一体架构的特性
    让Easysearch运行在LoongArch(3C5000L)上
    印象深刻的bug汇总(持续更新)
    FANUC机器人_KAREL编程入门(2)_通用IO信号的使用方法
    科技界年度大戏剧情终结:Open AI宣布ChatGPT创始人奥特曼回归
  • 原文地址:https://blog.csdn.net/weixin_42754896/article/details/126224779