内存溢出与内存泄露知识点总结

26 篇文章 0 订阅
本文详细介绍了Java中的内存溢出,包括堆内存溢出(无限申请对象)和栈内存溢出(无限递归调用),以及内存泄露的概念,指出其可能导致的后果。此外,还讲解了内存抖动的原因——频繁对象创建导致的垃圾收集问题,并给出了避免内存抖动的建议。通过对这些概念的理解,有助于优化程序性能并防止运行时错误。
摘要由CSDN通过智能技术生成

1. 内存溢出

程序在申请内存时,没有足够的内存可以申请,于是程序报错OOM(Out of Memory)。

JVM的内存空间,用的比较多的部分就是堆内存和栈内存,所以内存溢出也分为堆内存溢出和栈内存溢出的情况。

1.1 无限申请对象引起的堆内存溢出

ArrayList list = new ArrayList();
while(true){
	list.add(new Object());
}

由于在堆中申请的new ArrayList的被list所持有,所以当内存堆满之后,new ArrayList不会被回收

而内部申请的无数个Object被new ArrayList所持有,所以也不会被回收。由于无法回收内存,而同时正在申请新的内存,所以就报了OOM。

1.2 无限调用方法引起的栈内存溢出

public static void main(String[] args) {
    new Test().fun();
}

public void fun(){
    fun();
}

在JVM中,每调用一次方法,都会在java栈中生成一个新的栈帧,这些栈帧带有局部变量表,操作数栈,动态连接,方法返回地址等数据内容,会占用内存空间。而当我们无限的调用方法后,由于无法清栈,最终会导致栈内存溢出。

栈内存溢出JVM会报StackOverFlow的错误。

Exception in thread "main" java.lang.StackOverflowError
	at Test.fun(Test.java:13)
	at Test.fun(Test.java:13)
	at Test.fun(Test.java:13)
	......无数个同名方法......
	at Test.fun(Test.java:13)

报错的基本情况

  1. 同一个方法的反复调用,比如DFS的层数过多导致爆栈。
  2. 方法调用形成一个闭环,A调用B,B调用C,C调用D,D又调用A。于是方法一直被调用导致爆栈。
  3. 方法调用没有形成闭环,但是就是调用了太多的方法,导致爆栈。(不太可能)

2. 内存泄露

指程序在申请内存后,被某个对象一直持有,无法释放已经申请的内存空间。
当程序出现了多次内存泄露后,被无用内存占用的内存空间就会变多,可用的内存就会变少。
就更容易报OOM。

内存泄露的本质是:一个生命周期较长的对象,持有了一个生命周期较短的对象。导致生命周期短的对象在完成了他的任务之后,无法被系统所回收,导致的无用内存变多。

https://blog.csdn.net/qq_41872247/article/details/102996721

3. 内存抖动

是指在短时间内,有大量的对象被创建或者回收的情况。造成的原因是频繁在循环中创建对象。

由于创建对象非常频繁,且新对象需要内存。一旦内存空间不足,就会触发GC,回收掉不需要使用的内存。
内存抖动就是指频繁创建对象而导致的频繁触发GC的情况。

GC一旦被频繁触发,就会导致应用程序卡顿。

fastjson使用时,将json转成javabean时就会触发内存抖动。

如何避免:
不要在会频繁调用的方法中,创建对象,而改用成员变量的方式。比如说view的onDraw方法,onTouchEvent方法等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值