Java学习笔记-Java内存溢出

本文探讨了Java内存的堆和栈区域,详细分析了StackOverFlowError和OutOfMemoryError的区别,重点关注Java堆溢出的问题,包括其原因和简单的解决思路,如设置堆转储快照进行分析。此外,还讲解了虚拟机栈和本地方法栈、方法区与运行时常量池以及直接内存溢出的情况。
摘要由CSDN通过智能技术生成

堆和栈

Java堆是Java虚拟机管理的最大的一块内存,是一块被所有线程共享的内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放数据实例,Java世界里“几乎”所有的对象实例都在这里分配内存。(《Java虚拟机规范》中说到:“所有的对象实例以及数组都应该在堆上分配”)。

Java中栈通常指Java虚拟机栈,或者更多时候指的是局部变量表部分。
局部变量表存放了编译期可知的各种Java虚拟机基本数据类型,对象引用和ReturnAddress类型(指向了一条字节码指令的地址)。

StackOverFlowError

当线程请求的栈深度超过大于虚拟机所允许的深度时,会抛出StackOverFlowError异常(如果Java虚拟机栈容量可以动态扩展(HotSpot虚拟机的选择是不支持扩展),那么就不会有这个异常,当扩展到内存不够时,就会是OutOfMemoryError异常)。

为什么HotSpot默认是不支持扩展:个人认为是因为StackOverFlowError的影响比OutOfMemoryError影响小一点。因为StackOverFlowError的影响范围发生该异常的线程自己,如果发生OutOfMemoryError异常,因为内存是所有线程都在使用的,如果发生OutOfMemoryError,那么会影响到其他功能。

OutOfMemoryError

除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError的可能。

Java堆溢出

Java堆是用来存储对象实例的,只要我们不断的创建对象并保证GC Roots到对象之间有可达路径,那么当对象数量触及最大堆的容量时,就会出现内存溢出异常。

简单解决思路

通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出的时候Dump出当前的内存堆转储快照以便进行分析。
通过内存映像分析工具对Dump出的堆转储快照进行分析。

  • 先确认导致OOM的对象是否必要,即分清楚是出现了内存泄露(不必要,没回收)还是内存溢出(必要)。
  • 如果是内存泄露,那么进一步通过工具查看泄露对象到GC Roots的引用链,通过泄露对象的类型信息和引用链信息,找到具体代码位置,并且分析出导致无法回收的原因,进行解决。
  • 如果是内存溢出,那么就要比较Java虚拟机的堆参数和机器的内存,然后分析是否能向上调整空间。在从代码上检查是否存在对象生命周期过长,持有状态时间过长,存储的结构设计不合理等情况。

虚拟机栈和本地方法栈溢出

如果线程请求的栈深度大于虚拟机所允许的最大深度,那么就会发生StackOverFlowError
如果虚拟机栈空间允许动态扩展,当扩展栈容量无法申请到足够的内存时,将出想OutOfMemoryError。
因为HotSpot不支持动态扩展,所以除非是创建线程申请内存时就因无法获得足够内存导致OutOfMemoryError,否则都是StackOverFlowError。

StackOverFlowError异常时,会有明确的错误堆栈可供分析,相对而言比较容易定位到问题所在。

方法区和运行时常量池溢出

可以通过String::intern()进行运行时常量池的测试。
在JDK1.6及其以前版本,因为运行时常量池在方法区中,所以当常量池中的数据过多时,就会发生OutOfmemoryError。
而在JDK1.7以后,比如JDK1.7中,原本存在永久代的运行时常量池移Java堆中,此时限制方法区的容量是无意义的。而在JDK1.8中,将方法区中的所有东西都移到元空间中(本地内存),废弃了永久代的概念。

直接内存溢出

一个明显的特征就是heap dump 文件中不会看出什么明显异常情况。
如果发现发生内存溢出后产生的Dump文件很小,而程序中又直接或间接(典型的为NIO)的使用了directMemory(直接内存),那么就应该考虑重点检查一下直接内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值