【原创】android内存管理-内存泄漏原因
转载请注明出处 http://www.cnblogs.com/weiwangnuanyang/p/5704596.html
先讲一下内存泄漏的概念:内存泄露是指无用对象持续占有内存,或者内存得不到及时释放,从而造成的内存空间的浪费。
我们都知道,Java中对象的存储在堆中,它们由GC回收。GC为了能够正确释放对象,会监控每个对象的运行状况(申请、引用、被引用、赋值等)。Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。
因此Java中造成内存泄漏的一般原因都是长生命周期的对象持有了短生命周期的对象,使得短生命周期的对象不能被释放;或者资源未及时关闭。
下面总结了一些造成android中内存泄漏的常见原因:
1. 大量同一个类的对象被常驻内存的Map(比如单例模式的静态成员变量)持有,未及时移除。
比如观察者模式中的监听者,注册后没有反注册。
再比如使用一个很重的对象作为Map的key,导致这个类所引用的所有对象都不能释放。
所以如果注册监听时,监听的对象常驻内存,一定要反注册。尽量不使用很重的对象作为Map的key,如果有这样的需求,一定要及时清空Map.
2. Activity中使用非静态内部类或者匿名内部类,或者引用着Activity的类被其他长生命周期类持有。Activity持有其View层以及所有相关联资源的引用,如果无用的Activity得不到释放,会泄漏大量资源。
下面列举一些常见的情况。
(1)将Activity作为单例模式的静态成员变量。
(2)静态对象间接引用Activity.如下面代码的引用关系mDrawable -> ImageView -> MainActivity,导致Activity泄漏。
public class MainActivity extends Activity {
private static Drawable mDrawable;
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
ImageView iv = new ImageView(this);
mDrawable = getResources().getDrawable(R.drawable.ic_launcher);
iv.setImageDrawable(mDrawable);
}
}
(3)Activity的内部类作为其静态成员变量。非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,如下Demo会持有MainActivity,
public class MainActivity extends Activity
{
static Demo sInstance = null;
public void onCreate(BundlesavedInstanceState){
} class Demo{
void do Something(){
}
}
}
(4)Handler作为内部类引起的内存泄漏。如果Handler是非静态内部类,Handler 会持有Activity的引用。当Activity退出而Handler还有延迟处理的消息没有处理完,会导致Activity不能回收,反复如此会导致内存泄露。
(5)线程引起的内存泄漏。下面的代码中Tread运行不定时,在run方法未执行完的期间会一直持有Activity的引用。而AsyncTask的问题更严重写,AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题。
SampleActivity extends Activity {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
doSomething();
return null;
}
}.execute(); new Thread(new Runnable() {
@Override
public void run() {
doSomething();
}
}).start();
}
我们首先想到的解决方法是使用静态内部类,但是静态内部类又不持有Activity对象,所有当需要使用Activity的时候可以使用弱引用。
private static class MyHandler extends Handler { private final WeakReference<Context> context; private MyHandler(Context context) {
this.context = new WeakReference<Context>(context);
} @Override
public void handleMessage(Message msg) {
switch (msg.what) { }
}
} private final MyHandler mHandler = new MyHandler(this); private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { }
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// 发送一个10分钟后执行的一个消息
mHandler.postDelayed(sRunnable, 600000);
}
(6)Context引起的泄漏。一个app的Application会持有一个生命周期与app一样长的Context,每一个组件会持有一个与组件生命周期一样长的Context.当比Activity生命周期长的对象持有了Activity的Context,会引起Activity不能被回收。所以在允许的情况下,尽量使用ApplicationContext。
3. 资源未及时关闭
在实际开发中,经常需要在程序中打开一些物理资源,如数据库连接、网络连接、磁盘文件等,打开这些物理资源之后必须显式关闭,否则将会引起资源泄漏。
JVM的垃圾回收机制不会回收这些资源,垃圾回收机制属于java内存管理的一部分,它只是负责回收堆内存中分配出来的内存,至于程序中打开的物理资源,垃圾回收机制是无能为力的。
通常在finally块中关闭资源,有一个细节就是,最好在关闭资源时进行判空。
4. 合理管理Bitmap
以上部分内容摘自:
http://blog.csdn.net/mxm691292118/article/details/51020023
【原创】android内存管理-内存泄漏原因的更多相关文章
- [Android 性能优化系列]内存之基础篇--Android怎样管理内存
大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...
- Unity游戏Mono内存管理及泄漏
UWA工具 https://yq.aliyun.com/articles/435553 Unity游戏Mono内存管理及泄漏 https://wetest.qq.com/lab/view/135.ht ...
- 内存管理 & 内存优化技巧 浅析
内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户 ...
- Java中的垃圾回收机制&内存管理&内存泄漏
1. Java在创建对象时,会自动分配内存,并当该对象引用不存在的时候,释放这块内存. 为什么呢? 因为Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用时,就自动释放对象所 ...
- 构造函数,C++内存管理,内存泄漏定位
构造函数 1.构造顺序 虚基类构造函数,基类构造函数,类对象构造函数,自己的构造函数 2.必须使用初始化列表 (1) 引用成员,常量成员: (2) 基类没默认构造函数(自己重载覆盖了), (3)类对象 ...
- Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件
1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...
- Linux内核内存管理-内存访问与缺页中断【转】
转自:https://yq.aliyun.com/articles/5865 摘要: 简单描述了x86 32位体系结构下Linux内核的用户进程和内核线程的线性地址空间和物理内存的联系,分析了高端内存 ...
- Android 内存管理 &Memory Leak & OOM 分析
转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...
- 【转】Android中的内存管理--不错不错,避免使用枚举类型
原文网址:http://android-performance.com/android/2014/02/17/android-manage-memory.html 本文内容翻译自:http://dev ...
随机推荐
- Python使用re模块正则式的预编译及pickle方案
项目上线要求当中有言论和昵称的过滤需求, 客户端使用的是python脚本, python脚本中直接利用re模块来进行正则匹配, 一开始的做法是开启游戏后, 每帧编译2条正则式, 无奈运营需求里面100 ...
- Objective-C关键字和概念
Objective-C关键字和概念 @ 看到这个关键字,我们就应该想到,这是Object-C对C语言的扩展,例如@interface XXX. @interface 声明类 @implementati ...
- IO:OutPutStream
OutputStream类(java.io.OutputStream) public abstract class OutputStream extends Object implements Clo ...
- TCP/IP BOOKS
TCP/IP Fundamentals for Microsoft Windows: Overview https://technet.microsoft.com/en-us/library/bb72 ...
- css3 animation-fill-mode 对布局的影响
问题描述:在小米手机上,animation-fill-mode设置为 both时,在手机上的web页面会超出屏幕宽度,出现滚动条. 解决方法:animation-fill-mode设为none. .p ...
- E 最熟悉的陌生人 (纪念当年就读的梅州市江南高级中学)
最熟悉的陌生人 作者:张慧桥 枪与玫瑰” 负责审讯的兄弟真是好样的,回来后的第四天上午就让黄志深那小子招了出来. 这可真的不容易! 现在公安部对我们审讯工作有很多的规定,其中一条就是不准刑讯逼供,就是 ...
- mysql数据导出excel格式+乱码解决
1:导出的SQL命令,只需要加上“FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' ” ...
- Docker Registry服务启动过程浅析
当我们pull一个registry镜像或者自己制作一个镜像之后,使用命令docker run -d -p 5000:5000 registry,就可以启动一个私有容器服务,那么究竟是怎么做到的呢? 首 ...
- [Doxygen]Doxygen
1. Doxygen做什么? 首先这是一个文档生成工具,而不是代码中的注释生成工具.其次,如何生成对应文档,那就是按照一个配置文件中给出的配置格式来书写注释的时候,通过工具就可以解析代码注释最终生成文 ...
- 阿里weex学习入门必备
1.阿里weex学习前景 至于这些东西,可以参照一下链接去看看其作用.... http://share.iclient.ifeng.com/news/sharenews.f?forward=1& ...