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的语法进行查询。
标签:Java,space,OutOfMemoryError,线程,内存,JVM,堆栈 来源: https://www.cnblogs.com/liconglong/p/16248749.html