内存溢出问题排查

在这里插入图片描述
在这里插入图片描述

: 是运行时数据区,所有类的实例和数组都是在堆上分配内存
异常类型:java.lang.OutOfMemoryError: Java heap space
优化:通过–Xms(堆初始值) -Xmx(堆最大值)-Xmn(年轻代)参数设置

方法区(元空间): 常量、静态变量、类信息,元空间并不在虚拟机中,而是使用本地内存
异常类型:Java.Lang.OutOfMemoryErrorMetaspace
优化:通过-XX:MetaspaceSize -XX:MaxMetaspaceSize 参数设置

栈溢出
异常类型: java.lang.StackOverflowError 
优化:通过-Xss(每个线程的栈大小) 参数设置

默认堆中年轻代(Young)1/3,老年代(Old)2/3,年轻代中包含Eden区和Survivor区,Survivor区包含From(S0)区和To(),默认新生代中Eden区、From区、To区的比例为8:1:1,当Eden区内存不足时会触发Minor gc,没有被回收的对象进入到Survivor区,同时分代年龄+1,当再次触发Minor gc时,From区中的对象会移动到To区,Minor gc会回收Eden区和From区中的垃圾对象,对象的分代年龄会一次次的增加,当年龄增加到15以后,对象会进入到老年代。当老年代内存不足时,会触发Full gc,如果Full gc无法释放足够的空间,会触发OOM内存溢出,在进行Minor gc或Full gc时,会触发STW(Stop The World),即停止用户线程

参考:https://blog.csdn.net/hequnwang10/article/details/124879312
垃圾标记算法:
1.引用计数法: 对象的引用计数为0时,表示此对象可被垃圾收集器回收
2.可达性算法(目前Java中使用的内存标记算法):从一组根节点(GC Root Set)开始,通过递归搜索,建立对象的引用关系图,当搜索完毕后,图外的对象就是可回收对象

内存回收方式:
1.标记-清理算法(Mark and Sweep: 在存活对象占比高的情况下处理效率高,但不移动对象会引起内存碎片
2.标记-整理算法(Compacting: 把存活对象向内存前部空闲区域移动,执行成本较高,但可解决内存碎片问题
3.复制-清除算法(Copying: 把内存分为空闲区和对象区,当对象区满时,先采用跟踪算法对对象进行标记,再把存活对象拷贝到空闲区,清空原对象区,空闲区和对象区互换角色
4.分代回收策略
堆内存主要由新生代和老年代两部分组成。其中新生代由一个伊甸园(Eden)和两个幸存者Survivor FromSurvivor To 3部分组成,新创建对象首先保存在Eden中,当Eden中对象达到一定数量时,JVM触发Minor GC,GC时,先把EdenFrom中的存活对象拷贝到Survivor To区,再清除EdenFrom两个区域的数据,最后FromTo互换身份,完成一次内存回收。新生代区域对象数量大,存活时间短,一般采用复制-清除算法,通过这种结构和回收方式来提高垃圾回收效率,减少内存碎片。
经过若干(默认15)次后还存活的对象,将进入老年代区,当老年代数据满时,会触发Major GC(又称Full GC),此时新生代、老年代、元区域、直接内存区域都会执行GC操作。

垃圾收集器:
新生代垃圾收集器
老年代垃圾收集器
// JVM参数 jdk1.8及以上
参考:http://www.51gjie.com/java/551.html
-Xms: 堆初始内存
-Xmx: 堆最大可用内存

-Xmn: 年轻代大小
-XX:NewSize: 年轻代(Young Generation)的初始空间大小
-XX:MaxNewSize: 年轻代(Young Generation)的最大空间大小

-XX:NewRatio: 年轻代与老年代的比率, 默认2,老年代 : 年轻代 = 2 : 1
-XX:SurvivorRatio: SurvivorEden的比率, 默认8Eden : from : to = 8 : 1 : 1

-XX:MetaspaceSize: 元空间触发Fullgc的初始阈值, 默认是21M左右, 收集器根据gc回收情况会对该值进行调整
-XX:MaxMetaspaceSize: 元空间最大值, 默认-1, 即不限制

-Xss: 每个线程的栈大小

-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC

-Xmn-XX:NewSize/-XX:MaxNewSize-XX:NewRatio 3组参数都可以影响年轻代的大小,混合使用的情况下,优先级是什么?
高优先级:-XX:NewSize/-XX:MaxNewSize
中优先级:-Xmn
低优先级:-XX:NewRatio
推荐使用-Xmn参数

在这里插入图片描述

// OOM常见情况
参考:https://blog.csdn.net/dyangel2013/article/details/121533667
java.lang.OutOfMemoryError: Java heap space ()
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: GC overhead limit exceeded
Java.lang.OutOfMemeoryError:unable to create new native thread (多次JVM花费了98%的时间进行垃圾回收,而只得到2%可用的内存)
// idea设置jvm运行堆内存大小
-Xms128m -Xmx128m

public class Main {
    public static void main(String[] args) {
        // 返回Java虚拟机中的堆内存总量
        long xmsMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        // 返回Java虚拟机中使用的最大堆内存
        long xmxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
        System.out.println("-Xms:" + xmsMemory + "M");
        System.out.println("-Xmx:" + xmxMemory + "M");

        ArrayList<Byte[]> list = new ArrayList<>();
        while (true) {
            list.add(new Byte[1 * 1024 * 1024]);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}


// 报内存溢出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at org.example.Main.main(Main.java:19)
实例:分析Minor GC 和 Full GC
-Xms:123M
-Xmx:123M
0.985: [GC (Allocation Failure) [PSYoungGen: 32704K->5115K(38400K)] 32704K->29727K(125952K), 0.0147298 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 
1.781: [GC (Allocation Failure) [PSYoungGen: 36437K->5096K(38400K)] 61049K->58509K(125952K), 0.0145874 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 
2.570: [GC (Allocation Failure) [PSYoungGen: 34703K->5064K(38400K)] 88117K->87149K(125952K), 0.0169763 secs] [Times: user=0.06 sys=0.00, real=0.02 secs] 
2.587: [Full GC (Ergonomics) [PSYoungGen: 5064K->0K(38400K)] [ParOldGen: 82085K->87055K(87552K)] 87149K->87055K(125952K), [Metaspace: 3704K->3704K(1056768K)], 0.0761033 secs] [Times: user=0.20 sys=0.00, real=0.08 secs] 
3.437: [Full GC (Ergonomics) [PSYoungGen: 29289K->28672K(38400K)] [ParOldGen: 87055K->87055K(87552K)] 116345K->115728K(125952K), [Metaspace: 3704K->3704K(1056768K)], 0.0355179 secs] [Times: user=0.05 sys=0.00, real=0.04 secs] 
3.578: [Full GC (Ergonomics) [PSYoungGen: 32768K->32768K(38400K)] [ParOldGen: 87055K->87055K(87552K)] 119824K->119824K(125952K), [Metaspace: 3704K->3704K(1056768K)], 0.0340281 secs] [Times: user=0.08 sys=0.00, real=0.03 secs] 
3.612: [Full GC (Allocation Failure) [PSYoungGen: 32768K->32768K(38400K)] [ParOldGen: 87055K->87005K(87552K)] 119824K->119773K(125952K), [Metaspace: 3704K->3704K(1056768K)], 0.0746217 secs] [Times: user=0.06 sys=0.02, real=0.07 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D://\java_pid6308.hprof ...
Heap dump file created [245257624 bytes in 0.514 secs]
Heap
 PSYoungGen      total 38400K, used 33280K [0x00000000fd580000, 0x0000000100000000, 0x0000000100000000)
  eden space 33280K, 100% used [0x00000000fd580000,0x00000000ff600000,0x00000000ff600000)
  from space 5120K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffb00000)
  to   space 5120K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x0000000100000000)
 ParOldGen       total 87552K, used 87009K [0x00000000f8000000, 0x00000000fd580000, 0x00000000fd580000)
  object space 87552K, 99% used [0x00000000f8000000,0x00000000fd4f8620,0x00000000fd580000)
 Metaspace       used 3734K, capacity 4540K, committed 4864K, reserved 1056768K
  class space    used 417K, capacity 428K, committed 512K, reserved 1048576K
// arthas排查
下载arthas
https://arthas.aliyun.com/arthas-boot.jar

启动arthas
java -jar arthas-boot.jar

dashboard查看总面板数据
arthas排查CPU占有率高问题
	thread 查看下总体线程的资源使用信息
	thread id 查看线程的具体信息

arthas排查死锁问题
	thread -b

Arthas 使用场景:
是否有一个全局视角来查看系统的运行状况? dashboard
为什么 CPU 又升高了,到底是哪里占用了 CPU ? thread
运行的多线程有死锁吗?有阻塞吗? tread -b
程序运行耗时很长,是哪里耗时比较长呢?如何监测呢? trace
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? sc
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? jad
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?watch
有什么办法可以监控到 JVM 的实时运行状态? jvm

在这里插入图片描述

// dump文件
配置jvm参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump/xxx.hprof
发生OOM会在HeapDumpPath路径下生成一个.hprof文件
hprof分析工具:Memory Analyzer (MAT)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值