关于内存泄露的总结

大致先分为五个小模块:

1、什么是内存泄漏

2、有哪些情况会导致内存泄漏切如何解决

3、如何检测内存泄漏

4、Java得基本数据类型和占用字节

5、什么是内存溢出和解决办法


一、什么是内存泄漏(Memory Leak)

内存泄漏是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。即所谓内存泄漏。

用大白话说就是是程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃,内存空间使用完之后没有回收。



二、有哪些情况会导致内存泄漏切如何解决

1.集合类泄漏

集合如果只有添加元素的方法,没有相应的删除机制,就会到之后内存被占用。

如果这个集合是全局的变量,没有相应的删除机制,就会导致集合占用的内存只增加不减。

2.单例造成的内存泄漏

单列的静态特性的生命周期和应用的生命周期一样长,如果使用不恰当,就会造成内存泄露。

3.匿名内部类/非静态内部类和异步线程

非静态内部类创建静态实例造成的内存泄漏

4.匿名内部类

Android 开发经常会继承继承实现activity、fragment、view,如果使用了匿名类,就异步线程持有,没有任何措施就会内存泄漏。

5.Handler 造成的内存泄漏

handler、message和messageQueue都是相互关联在一起的,万一handler发送的message没有被处理,

message和发送的handler对象被线程messagequeue一直持有。handler属于tls变量,生命周期和view,activity是不一致的,

导致无法正常释放。

6.尽量避免使用 static 成员变量

如果你的app进程设计上是长驻内存的,那即使app切到后台,这部分内存也不会被释放。按照现在手机app内存管理机制,

占内存较大的后台进程将优先回收,yi'wei如果此app做过进程互保保活,那会造成app在后台频繁重启。

当手机安装了你参与开发的app以后一夜时间手机被消耗空了电量、流量,你的app不得不被用户卸载或者静默。

7.避免 override finalize()

8.资源未关闭造成的内存泄漏

对于使用了BraodcastReceiver,ContentObserver,File,游标 Cursor,Stream,Bitmap等资源的使用,

应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

9.一些不良代码造成的内存压力


三、如何检测内存泄漏

1.使用调试器和C运行库(CRT)调试堆函数。

2.养成良好的代码习惯

3.1 内存泄露就是指在程序中出现动态分配的内存单元,使用结束后没有释放的情况。

3.2调试运行时,内存泄露一般屏幕上会现现memory leak字样的英文。

(还有很多方法可以检测内存泄露,这里就不列出来了)


四、Java得基本数据类型和占用字节

byte:1 字节 8 位

short:2 字节16 位

int:4 字节32 位

long:8 字节64 位

float:4 字节32 位

double:8 字节64 位

char:2 字节16 位


关于内存泄露的总结_第1张图片



五、什么是内存溢出和解决办法

什么是内存溢出:

      1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

  2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;

  3.代码中存在死循环或循环产生过多重复的对象实体;

  4.使用的第三方软件中的BUG;

  5.启动参数内存值设定的过小;

溢出的解决方法:

【情况一】:

java.lang.OutOfMemoryError:Javaheapspace:这种是java堆内存不够,一个原因是真不够(如递归的层数太多等),另一个原因是程序中有死循环;

  如果是java堆内存不够的话,可以通过调整JVM下面的配置来解决:

  -Xms3062m

  -Xmx3062m

【情况二】

  java.lang.OutOfMemoryError:GCoverheadlimitexceeded

  【解释】:JDK6新增错误类型,当GC为释放很小空间占用大量时间时抛出;一般是因为堆太小,导致异常的原因,没有足够的内存。

  【解决方案】:

  1、查看系统是否有使用大内存的代码或死循环;

  2、通过添加JVM配置,来限制使用内存:

  -XX:-UseGCOverheadLimit

【情况三】:

  java.lang.OutOfMemoryError:PermGenspace:这种是P区内存不够,可通过调整JVM的配置:

  -XX:MaxPermSize=128m

  -XXermSize=128m

  【注】:

  JVM的Perm区主要用于存放Class和Meta信息的,Class在被Loader时就会被放到PermGenspace,这个区域成为年老代,GC在主程序运行期间不会对年老区进行清理,

  默认是64M大小,当程序需要加载的对象比较多时,超过64M就会报这部分内存溢出了,需要加大内存分配,一般128m足够。

【情况四】:

  java.lang.OutOfMemoryError:Directbuffermemory

  调整-XX:MaxDirectMemorySize=参数,如添加JVM配置:

  -XX:MaxDirectMemorySize=128m

【情况五】:

  java.lang.OutOfMemoryError:unabletocreatenewnativethread

  【原因】:Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小了。

  【解决】:由于JVM没有提供参数设置总的stack空间大小,但可以设置单个线程栈的大小;而系统的用户空间一共是3G,

       除了Text/Data/BSS/MemoryMapping几个段之外,Heap和Stack空间的总量有限,是此消彼长的。因此遇到这个错误,

        可以通过两个途径解决:1.通过-Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError);

                  2.通过-Xms-Xmx两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用)。

【情况六】:

  java.lang.StackOverflowError

  【原因】:这也内存溢出错误的一种,即线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小。

  【解决】:优化程序设计,减少方法调用层次;调整-Xss参数增加线程栈大小


(2) 在使用内存之前检查指针是否为NULL。假设指针p 是函数的參数,那么在函数的入口处用assert(p!=NULL)进行检查。假设是用malloc 或new 来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理。


具体参考:https://blog.csdn.net/hcmony/article/details/81105507

                 https://www.cnblogs.com/leasonWang/p/11146030.html


-----------------------------------------------------------------------------------------------有些是来源于百度,CSDN,博客园等。

你可能感兴趣的:(关于内存泄露的总结)