jvm问题解决方案

本文主要探讨JVM不同区域溢出问题及解决办法。包括堆溢出,因不断创建对象且避免回收导致;栈溢出,由线程请求栈深度过大或扩展栈时内存不足引发;方法区或元数据区溢出,与常量池满或类信息过多有关;本机直接内存溢出,常与NIO使用相关,并分别给出对应解决措施。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么情况下出现堆溢出?怎么解决?
    产生原因:
        堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收实例对象,就会在对象数量达到堆最大容量时产生OutOfMemoryError异常
    解决办法:
        使用-XX:+HeapDumpOnOutOfMemoryError可以让java虚拟机在出现内存溢出时产生当前堆内存快照以便进行异常分析,主要分析那些对象占用了内存(保存路径:-XX:HeapDumpPath=/XXX/XXX/,默认当前路径)
        也可使用jmap将内存快照导出,一般检查哪些对象占用空间比较大,由此判断代码问题,没有问题的考虑调整堆参数(jmap -dump:format=b,file=XXX [pid])

2、什么情况下出现栈溢出?怎么解决?
    产生原因:
        如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverFlowError
        如果虚拟机在扩展栈时无法申请到足够的内存空间,抛出OutOfMemeoryError
        栈默认深度是1M
    解决办法:
        StackOverFlowError一般是函数调用层级过多导致,比如死递归、死循环
        OutOfMemeoryError一般是在多线程环境才会产生,一般用“减少内存的方法”,既减少最大堆和减少栈容量来换取更多的线程支持

3、什么情况下出现方法区或元数据区溢出?怎么解决? 
    产生原因:
        jdk 1.6以前,运行时常量池还是方法区一部分,当常量池满了以后(主要是字符串变量),会抛出OOM异常
        方法区和元数据区还会用于存放class的相关信息,如:类名、访问修饰符、常量池、方法、静态变量等,当工程中类比较多,而方法区或者元数据区太小,在启动的时候,也容易抛出OOM异常
    解决办法:
        jdk 1.7之前,通过-XX:PermSize,-XX:MaxPermSize,调整方法区的大小
        jdk 1.8以后,通过-XX:MetaspaceSize,-XX:MaxMetaspaceSize,调整元数据区的大小

4、什么情况下出现本机直接内存溢出?怎么解决?
    产生原因:
        jdk本身很少操作直接内存,而直接内存(DirectMemory)导致溢出最大的特征是,Heap Dump文件不会看到明显异常,而程序中直接或者间接的用到了NIO
    解决办法:
        直接内存不受java堆大小限制,但受本机总内存的限制,可以通过MaxDirectMemorySize来设置(默认与堆内存最大值一样)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值