网站首页 > java教程 正文
Java内存溢出即程序在申请内存时,没有足够的空间供其使用,出现out of memory。常见于四种情况:栈溢出(StackOverflowError)、堆溢出(OutOfMemoryError:java heap space)、永久代溢出(OutOfMemoryError: PermGen space)、OutOfMemoryError:unable to create native thread,以下一一进行总结。
1、栈溢出
首先搞清楚java栈空间存储的是什么。java栈空间是线程私有的,是java方法执行的内存模型。每个方法执行时都会在java栈空间产生一个栈帧,存放方法的变量表,返回值等信息,方法的执行到结束就是一个栈帧入栈到出栈的过程。
所以栈溢出的原因一般是循环调用方法导致栈帧不断增多,栈深度不断增加,最终没有内存可以分配,出现StackOverflowError,比如下面这种情况:
public class stack{
public void test(){
this.test();
}
public static void main(String[] args){
for(; ; ;)
new stack().test;
}
}
栈内存溢出一般是程序错误导致,如递归死循环等等。
2、堆溢出
java堆是线程共有的区域,主要用来存放对象实例,几乎所有的java对象都在这里分配内存,也是JVM内存管理最大的区域。java堆内存分年轻代和年老代,堆内存溢出一般是年老代溢出。当程序不断地创建大量对象实例并且没有被GC回收时,就容易产生内存溢出。当一个对象产生时,主要过程是这样的:
JVM首先在年轻代的Eden区为它分配内存;
若分配成功,则结束,否则JVM会触发一次Young GC,试图释放Eden区的不活跃对象;
如果释放后还没有足够的内存空间,则将Eden区部分活跃对象转移到Suvivor区,Suvivor区长期存活的对象会被转移到老年代;
当老年代空间不够,会触发Full GC,对年老代进行完全的垃圾回收;
回收后如果Suvivor和老年代仍没有充足的空间接收从Eden复制过来的对象,使得Eden区无法为新产生的对象分配内存,即溢出。
由此可见,当程序不断地创建大量对象实例并且没有被GC回收时,就容易产生内存溢出。如下:
public class heap{
public static void main(String[] args){
ArrayList list = new ArrayList();
while(true){
list.add(new heap());
}
}
}
堆内存溢出很可能伴随内存泄漏,应首先排查可能泄露的对象,再通过工具检查GC roots引用链,从而发现泄露对象是由于何种引用关系使得GC无法回收他们;若不存在内存泄漏,换句话说就是内存中的对象还都需要继续存活,则可通过修改虚拟机的堆参数将堆内存增大。
3、永久代溢出
永久代也是java堆内存的一部分,主要用来存放Class的相关信息,如类名,访问修饰符等等。一般永久代溢出的原因是动态加载大量的Class并且没有及时被GC回收。只能通过调整永久代内存参数的方式解决。
4、无法创建本地线程
我们知道,操作系统对每个进程的内存都是有一定限制的,当堆内存和非堆内存分配过大时,剩余的内存不足以创建足够的线程栈,就会产生OutOfMemoryError。因此我们可以增大进程占用的总内存或减小堆内存等来解决问题。
总结:
栈内存溢出:程序所要求的栈深度过大导致。
堆内存溢出:分清 内存泄露还是 内存容量不足。泄露则看对象如何被 GC Root 引用。不足则通过 调大 -Xms,-Xmx参数。
持久带内存溢出:Class对象未被释放,Class对象占用信息过多,有过多的Class对象。
无法创建本地线程:总容量不变,堆内存,非堆内存设置过大,会导致能给线程的内存不足。
————————————————
版权声明:本文为CSDN博主「code_kkk」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
https://blog.csdn.net/code_kkk/article/details/82939773
猜你喜欢
- 2024-11-02 Java堆内存又溢出了!看大师如何防范
- 2024-11-02 并发编程中常见的内存溢出的三种情况
- 2024-11-02 jmeter内存溢出解决方法(jmeter怎么清理缓存)
- 2024-11-02 JAVA服务实例内存高问题排查及解决!牛掰
- 2024-11-02 面试官:你知道JVM内存溢出问题的定位方法吗?
- 2024-11-02 简述 JVM 基础(二):Java内存区域与内存溢出异常
- 2024-11-02 一次大量出现Full GC、内存泄漏问题及内存溢出错误排查和分析
- 2024-11-02 如何识别Java中的内存泄漏(如何识别java中的内存泄漏情况)
- 2024-11-02 java 面试专题一:(Java基础)第三篇常见内存溢出异常问题
- 2024-11-02 JAVA 8 内存溢出总结(java内存溢出会导致应用停机吗)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)