jvm 各个运行数据区异常

本文详细解析了Java虚拟机(JVM)中的各种内存溢出情况,包括堆溢出、虚拟机栈和本地方法栈溢出、方法区及运行时常量池溢出,以及本机内存直接溢出等问题。针对每种情况提供了相应的参数设置和解决方案。

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

jvm: OutOfMemoryError 异常
在jvm规范中 除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OOM异常的可能。
一、jvm堆溢出:
只要不断的创建对象,并且保证GC Roots到对象之间有可达的路径来避免回收机制清楚这些对象,那么在对象的数量大到超过堆容量的时候就会发生内存溢出异常。
参数:-Xmx 最大堆内存
-Xms 最小堆内存
-XX:HeapDumpOnOutOfMemoryError 在虚拟机内存溢出的时候 将当前内存堆的快照转存以便事后分析
伪代码:

class HeapOOM{
main(String[] args){
 List <A> list =new ArrayList<>();
 while(true){
  list.add(new A())
 }

}

}
class A{
}
--------------------------
运行结果:
java.lang.OutOfMemoryError: Java heap space

    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:261)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
    at java.util.ArrayList.add(ArrayList.java:458)
    at Test.test01(Test.java:15

解决方案:通过内存映像分析工具堆dump出来的内存快照进行分析,重点是确认内存中的对象是否是必要的,先分析清楚是内存泄漏还是内存溢出;
内存泄漏,进一步查看泄漏对象到GC Roots的引用链,就能发现为什泄漏对象没有被GC收集
如果是必要存在的对象,就查看设置的堆参数以及查看代码中是否有生命周期过长、持有状态时间过长的情况。
二、虚拟机栈和本地方法栈溢出
在hostSpot虚拟机中不区分本地方法栈和虚拟机栈,因此在hostSpot虚拟机中-Xoss参数(设置本地方法栈的参数)是没有用的,栈的大小只有参数-Xss参数设定
这两种栈在虚拟机规范中有两种异常
1.OOM(在虚拟机扩展栈时无法申请到足够内存的时候)
2.StackOverflowError(线程请求的栈深度大于虚拟机所允许的最大深度)

注意:多线程减少栈内存可以避免栈溢出

三、方法区和运行时常量池溢出
由于常量池属于方法区的一部分,所以放到一起说,
参数:-XX:PermSize和-XX:MaxPermSize限制方法区的大小
这里的代码实验用的字符串的intern();
String intern() jdk1.6 与1.7的实现不一样
1.6是复制实例对像到方法区的常量池,
1.7是存储首次出现的引用地址
四、本机内存直接溢出
-XX:MaxDirectMemorySize 不指定默认与堆大小相等
directMemory导致内存溢出一个明显的特征就是在Heap Dump文件中不会看见明显的异常,如果发现OOM之后的Dump文件很小,而程序中使用了NIO很有可能就是这方面原因

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值