ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

内存泄漏相关问题分析

2022-07-10 18:06:01  阅读:271  来源: 互联网

标签:分析 泄漏 java 变量 回收 内存 Activity


java内存泄漏基础知识

简单说就是该被释放的对象一直没有释放,一直被某个对象持有导致不能垃圾回收。

java内存分配策略

静态存储区

主要存放静态数据,全局变量等。
这块内存在程序编译的时候已经分配好了,并且静态存储区中存储的变量在程序运行期间一直存在

栈区

方法体内的局部变量会在栈区内创建内存空间,并在方法执行结束后,这些变量持有的内存会被自动释放
因为栈内存分配运算内置于处理器当中,所以效率很高

但是栈区的内存空间容量有限

堆区

堆区又称为动态内存分配

通常用来存放new出来的对象和数组
这部分内存在不使用的时候将由java的垃圾回收器进行回收

栈区和堆区的区别

栈区是方法体内定义的一些基本类型的变量和对象的引用变量,都是在方法的栈内存中分配的。
当在一段方法中定义一个变量时,java就会在栈中为该变量分配内存空间,当超过这个变量的作用域时,这个变量也就无效了,分配给它的内存空间也将被释放掉。这时候栈区分配的空间就可以被其他方法继续使用

堆区所存储的是所有new出来的对象和数组,在堆中分配的内存将由java的垃圾回收器来自动管理,其中产生的数组或者对象还可以在栈中定义一个特殊的变量,而这个变量就是在栈区所存储内存的地址。

java是如何管理内存的

image

比如图中,根定点可达的对象都是有效对象,GC的时候不会回收。
但是Object2这个对象,跟根定点之间没有引用链,是可以被垃圾回收的。

java中的内存泄漏

内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄漏
内存泄漏的不断积累,会造成OOM,内存溢出

android内存泄漏

单例

image

不恰当的使用单例会造成内存泄漏

单例的静态特性使得它的生命周期和app的生命周期是一样的
就是说如果一个对象不再需要使用,而单例对象一直持有这个对象的引用,那么这个对象将不能被正常释放,这就造成了内存泄漏。

比如代码中传入得conext是Activity的context,Activity在回收的时候由于被单例持有导致无法回收。

正确写法:
image

通过application的context代替Activity的context。单例的生命周期和application的生命周期是一样的。不会造成Activity回收不了。

匿名内部类

image

在Activity中有一个匿名内部类,TestResource,每次启动这个Activity时,都会使用整个类里面的一些数据。
这样虽然避免了资源的重复创建,但是这种写法会造成内存泄漏。
为什么?
因为java中非静态内部类默认会持有外部类的引用。
而又使用该内部类创建一个静态实例的话,比如TAG,该实例生命周期就和应用的一样长。就导致该静态实例一直持有该Activity的引用。

正确写法:
image

改成静态内部类,这样就不会持有外部类的引用,从而就不会有内存泄漏的问题。

Handler

image

这种Handler的写法就会造成内存泄漏,因为这种写法,创建的MHandler是Handler的非静态内部类的实例。持有外部类Activity的引用。
而Handler的消息队列是在looper中不断地轮询处理,当这个Activity要退出的时候,消息队列中还有未处理或者正在处理的消息,而消息队列中的Message又持有mHandler的实例引用,mhandler又持有了Activity的引用,导致Activity无法被回收。造成内存泄露

正确写法:

image

首先创建静态内部类MyHandler,然后持有的外部类Activity才用弱引用。
弱引用会在垃圾回收时立即回收,因此不会造成内存泄露。

尽量避免使用static变量

如果把成员变量声明为static,它的生命周期就和整个app的生命周期是一致的。这样就会导致一个问题,如果你的app进程,设计上是常驻内存的,那即使app切到后台,这部分static变量也是不会被释放的。

按照现有的内存管理机制,后台占用内存较大的应用将优先被回收。所以说当你的进程被回收了之后,你所存在的那些变量数据是不安全的。
在类设计的时候可以考虑懒加载,尽量避免static成员变量。

资源未关闭的内存泄漏

比如经常使用的广播接收者,bitmap,socket等,这些资源在Activity销毁时,需要关闭或者注销这些资源。
否则这些资源将不会被回收。

AsyncTask造成的内存泄漏

原因和Handler是一样的。
和Handler不同的是可以在Activity的onDestroy方法中执行AsyncTask的cancel方法,避免内存泄漏。

标签:分析,泄漏,java,变量,回收,内存,Activity
来源: https://www.cnblogs.com/cfdroid/p/16463610.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有