Android之内存抖动、内存泄漏、内存溢出(OOM)

概念:

内存泄漏:是代码逻辑错误导致的,本应该释放的对象,由于有强引用,导致其不能被垃圾回收器回收。可以看我写的另一篇文章内存泄露(Memory Leak)

内存溢出(OOM):需要内存,可是申请不到足够的内存了,就会报错崩溃。所以内存泄漏不一定会导致OOM

内存溢出,主要分为堆内存溢出(OutOfMemoryError)、栈内存溢出(stackOverFlowError)和方法区内存溢出,平时可能接触到的是OutOfMemoryError和StackOverFlowError,主要还是OutOfMemoryError。

(1)StackOverFlowError是指线程存储调用函数的栈被用完了,我们知道调用一个函数就会生成一个代表被调用函数的栈帧压栈,函数执行完就会出栈。在一直递归调用的情况下,只有压栈操作没有出栈,会导致栈内存溢出,在平时开发过程中很难遇到。

递归调用太深,可能导致栈溢出

(2)OutOfMemoryError是指堆内存溢出,就是创建了大量的对象一直有强引用,导致对象一直不能被回收,最终导致堆内存被消耗完。其实一般也是代码逻辑错误导致的。

比如递归调用的时候,每个递归函数中都吃到大量的对象引用,递归深度足够大时,由于这些大量的对象,都被栈里的引用指向着,因为没有出栈操作,一直释放不掉,所以就发生了OOM。

再比如死循环执行逻辑,循环体内会创建大量的对象,并且这些对象被循环体外部引用,这样也会导致OOM。这里需要注意的是,循环体内创建的大量对象如果只是在循环体内使用,是不会造成OOM的,可能会导致内存抖动。

JAVA递归导致内存溢出问题

java 内存溢出 栈溢出的原因与排查方法

内存抖动:内存频繁的分配和回收导致内存不稳定。表现就是内存忽高忽低,有短时间内快速上升和下降的趋势,内存成锯齿状。内存抖动说明是在频繁的GC。看了一些文章,意思是频繁的GC,不一定会导致卡顿,而是分配内存的速度比回收内存的速度快,当释放足够内存满足应用需求的时候,GC的时候会很长, 会导致跳帧卡顿,严重时会导致OOM。

为什么Java中有垃圾回收机制,还会发生内存泄露或内存溢出呢?

因为,垃圾回收机制只是帮忙我们在对象在不“需要”的情况下把对象用的内存回收,只不过在C++中是需要程序员手动回收的。但是,对象需不需要是程序员控制的,发生内存泄露或内存溢出是因为对象需不需要没有控制到导致的。不过,在C++中,即便对象需不需要控制好了,没有手动释放不需要的对象,也会导致内存泄漏或者内存溢出。

总结一下:

在java内存泄露或内存溢出,只和程序员有没有把对象需不需要控制好,就是说,需要释放的对象,是不能有强引用指向这个对象的。

在C++中,内存泄露或内存溢出,可能是程序员没有把对象需不需要控制好,也可能是程序员没有把不需要的对象手动释放了。

检测:

我们用Memory Profiler

Android内存分析工具:Memory Profiler

Android内存分析工具 — Memory Profiler

Android | App内存优化 之 内存抖动解决实战

下面这篇文章不错

手把手讲解--性能优化案例(3)内存抖动和泄漏的优化

你可能感兴趣的:(Android,android,java,OOM,内存泄露)