JVM内存堆栈分析

一、JVM线程堆栈数据分析

  JVM 内部线程主要分为以下几种:

    VM 线程:单例的 VMThread 对象,负责执行 VM 操作;

    定时任务线程:单例的 WatcherThread 对象, 模拟在 VM 中执行定时操作的计时器中断;

    GC 线程:垃圾收集器中,用于支持并行和并发垃圾回收的线程;

    编译器线程: 将字节码编译为本地机器代码;

    信号分发线程:等待进程指示的信号,并将其分配给Java 级别的信号处理方法。

  GC进行垃圾回收时,会STW,那么GC是如何让所有的用户线程都停止呢?其使用的是安全点,实现原理如下:

    1、方法代码中被植入的安全点检测入口;

    2. 线程处于安全点状态:线程暂停执行,这个时候线程栈不再发生改变;

    3. JVM 的安全点状态:所有线程都处于安全点状态。

  JVM 支持多种方式来进行线程转储:

    1. JDK 工具, 包括: jstack 工具, jcmd 工具,jconsole,jvisualvm, Java Mission Control 等;

    2. Shell 命令或者系统控制台,比如 Linux 的 kill -3,Windows 的 Ctrl + Break 等;

    3. JMX 技术, 主要是使用 ThreadMxBean。

                

 

 

  fastthread 线程分析:(https://fastthread.io/)

        

二、内存分析与相关工具

  1、OutOfMemoryError: Java heap space

  创建新的对象时,堆内存中的空间不足以存放新创建的对象产生的原因。其实清楚了原因,问题就很容易解决了:只要增加堆内存的大小,程序就能正常运行。另外还有一些情况是由代码问题导致的:

    超出预期的访问量/数据量:应用系统设计时,一般是有 “容量” 定义的,部署这么多机器,用来处理一定流量的数据/业务。 如果访问量突然飙升,超过预期的阈值,类似于时间坐标系中针尖形状的图谱。那么在峰值所在的时间段,程序很可能就会卡死、并触发 ava.lang.OutOfMemoryError: Java heap space 错误。

    内存泄露(Memory leak):这也是一种经常出现的情形。由于代码中的某些隐蔽错误,导致系统占用的内存越来越多。如果某个方法/某段代码存在内存泄漏,每执行一次,就会(有更多的垃圾对象)占用更多的内存。随着运行时间的推移,泄漏的对象耗光了堆中的所有内存,那么 java.lang.OutOfMemoryError: Javaheap space 错误就爆发了。

  2、OutOfMemoryError: PermGen space/OutOfMemoryError: Metaspace

    java.lang.OutOfMemoryError: PermGen space 的主要原因,是加载到内存中的类数量太多或体积太大,超过了 PermGen 区的大小。

    解决办法:增大 PermGen/Metaspace

      -XX:MaxPermSize=512m

      -XX:MaxMetaspaceSize=512m

    高版本 JVM 也可以:

      -XX:+CMSClassUnloadingEnabled

  3、OutOfMemoryError: Unable to create new native thread

    java.lang.OutOfMemoryError: Unable to create new native thread 错误是程序创建的线程数量已达到上限值的异常信息。

    解决思路:

      1. 调整系统参数 ulimit -a,echo 120000 > /proc/sys/kernel/threads-max

      2. 降低 xss (为jvm启动的每个线程分配的内存大小)等参数

      3. 调整代码,改变线程创建和使用方式

三、内存分析工具

  1、Eclipse MAT:https://www.cnblogs.com/loong-hon/p/10475143.html

   2、jhat:堆转快照分析工具

  jhat和jmap是对着使用的,jhat用以分析jmap生成的堆转快照文件,但是一般不这么用,一般会使用可视化工具查看。

  使用jhat+快照文件命令后,出现already后即可使用

      

   从上图可以看到端口号为7000,在浏览器访问local host:7000

      

   可以看到分析结果是以包为单位进行分组显示的,分析内存泄漏问题是要会用到其中的Heap Histogram与OQL页签的功能,Heap Histogram可以找到内存中总容量最大的对象,OQL是标准的对象查询语言,使用类似SQL的语法进行查询。

posted @ 2022-05-09 12:22  李聪龙  阅读(690)  评论(0编辑  收藏  举报