前言
开发之中,很多时候会碰见内存泄漏和内存溢出。
而我们平常开发过程久了,可能弄混乱了其中的关系。
在这里想重新梳理一下内存泄漏和内存溢出。
1. 内存泄漏 Memory Leak
内存泄漏指我们向系统申请了内存,但是一直持有该内存空间,没有进行合理的释放,导致内存空间被浪费。
简而言之就是:应该被回收的对象,没有被垃圾回收释放内存空间。
常见的内存示例有:静态(static)集合对象引起的内存泄漏,因为静态对象的生命周期和JVM虚拟机一致。所以该对象是不会被系统垃圾回收机制回收并释放的。如果不合理的静态对象就会造成内存大量占用。
数据库连接,IO连接等管道对象引起的内存泄漏,这些创建的链接对象如果没有合理的关闭,那么系统并不会回收对应的对象,会导致这些资源持续的占用内存而无法被GC回收。
变量生命周期不合理引用造成的内存泄漏,常见的就是一个对象没有被使用后,我们未及时将对象设置为null,造成对象长时间占用。
引用了外部类的非静态内部类造成的内存泄漏,我们使用匿名类初始化的时候总是需要依赖外部类的实例,内部类对象隐式地持有外部类对像的引用,使得GC不能正确的回收造成的内存占用。
还有很多。但是总结来说就是我们不当使用对象而没有正确的用完释放而造成的内存占用,最终引发内存泄漏。
2. 内存溢出 Out Of Memory
内存溢出指我们向系统申请内存时,系统发现没有足够的内存空间可以分配。
下面结合java
进行介绍一下相关的溢出现象。以下现象都是内存溢出。
2.1 堆溢出
在java
中我们需要不断创建对象实例,并且保证GC
到对象之间有可达路径来避免垃圾回收机制清除这些对象。
也就是该对象实例被引用和使用,当程序运作过程中随着对象数据的增加,总容量触及最大堆的容量限制,就会造成内存溢出异常
java.lang.OutOfMemoryError
就是典型的堆栈空间被占满造成的内存溢出问题。
2.2 栈溢出
我们本地创建线程时如果向虚拟机申请大于虚拟机允许的空间,那么虚拟机将会抛出StackOverflowError
异常。
常见的栈容量过小,只要当新的栈帧内存无法分配的时候,都会抛出StackOverflowErroryi
异常。
2.3 场景
常见的造成内存溢出的场景有:
1.内存中加载的数据量过于庞大,例如一次性从数据库中读取过多的数据。
2.移动开发中常见的,一次性加载过大的Bitmap对象在内存中。
3.集合类中存在大量对象的引用,并且使用完毕后未进行清空造成的溢出。
4.代码中循环过程中产生过多的重复对象(重复创建新对象)。
5.设置的程序启动分配的内存值过小。
3. 后记
就是我们不当使用内存,造成内存被大量无效消耗,造成系统剩余可分配内存不足(内存使用泄漏了),后续程序继续申请时系统已经没有多余内存可以分配了(内存使用溢出了)。
我们乱用内存并使得系统正确回收内存(内存泄漏)。
我们申请内存空间超过了系统可分配的空间(内存溢出)。