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

内存溢出与内存泄露

  • 1. 内存溢出
    • 1.1 无限申请对象引起的堆内存溢出
    • 1.2 无限调用方法引起的栈内存溢出
  • 2. 内存泄露
  • 3. 内存抖动

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方法等。

你可能感兴趣的:(JAVA,Android,java,开发语言)