首页 首页 服务大厅 服务大厅 家修学院 家修学院 家修问答 家修问答 热门标签 热门标签 关于我们 关于我们
地址首页 > 新闻资讯 > 电脑维修 > 内存泄漏的原因及解决办法是什么

内存泄漏的原因及解决办法是什么

发布时间: 2023-03-08 来源: 简单到家维修服务
标签: 阅读量: 584

本教程操作环境:windows7系统、Dell G3电脑

常见的内存泄露造成的原因1、单例造成的内存泄漏

由于单例的静态特性使得其生命周期和应用的生命周期一样长,如果一个对象已经不再需要使用了,而单例对象还持有该对象的引用,就会使得该对象不能被正常回收,从而导致了内存泄漏。

示例:防止单例导致内存泄漏的实例

// 使用了单例模式

public class AppManager {

private static AppManager instance;

private Context context;

private AppManager(Context context) {

this.context = context;

}

public static AppManager getInstance(Context context) {

if (instance != null) {

instance = new AppManager(context);

}

return instance;

}

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

例如,有时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源,可能会出现如下写法:

public class MainActivity extends AppCompatActivity {

private static TestResource mResource = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

if(mResource == null){

mResource = new TestResource();

}

//...

}

class TestResource {

//...

}

}3、Handler造成的内存泄漏

示例:创建匿名内部类的静态对象

public class MainActivity extends AppCompatActivity {

private final Handler handler = new Handler() {

@Override

public void handleMessage(Message msg) {

// ...

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

new Thread(new Runnable() {

@Override

public void run() {

// ...

handler.sendEmptyMessage(0x123);

}

});

}

}1、从Android的角度

当Android应用程序启动时,该应用程序的主线程会自动创建一个Looper对象和与之关联的MessageQueue。当主线程中实例化一个Handler对象后,它就会自动与主线程Looper的MessageQueue关联起来。所有发送到MessageQueue的Messag都会持有Handler的引用,所以Looper会据此回调Handle的handleMessage()方法来处理消息。只要MessageQueue中有未处理的Message,Looper就会不断的从中取出并交给Handler处理。另外,主线程的Looper对象会伴随该应用程序的整个生命周期。

2、 Java角度

在Java中,非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用,但是静态内部类却不会。

对上述的示例进行分析,当MainActivity结束时,未处理的消息持有handler的引用,而handler又持有它所属的外部类也就是MainActivity的引用。这条引用关系会一直保持直到消息得到处理,这样阻止了MainActivity被垃圾回收器回收,从而造成了内存泄漏。

解决方法:将Handler类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

4、线程造成的内存泄漏

示例:AsyncTask和Runnable

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

new Thread(new MyRunnable()).start();

new MyAsyncTask(this).execute();

}

class MyAsyncTask extends AsyncTask {

// ...

public MyAsyncTask(Context context) {

// ...

}

@Override

protected Void doInBackground(Void... params) {

// ...

return null;

}

@Override

protected void onPostExecute(Void aVoid) {

// ...

}

}

class MyRunnable implements Runnable {

@Override

public void run() {

// ...

}

}

}AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用。如果任务在Activity销毁之前还未完成,那么将导致Activity的内存资源无法被回收,从而造成内存泄漏。

解决方法:将AsyncTask和Runnable类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

5、资源未关闭造成的内存泄漏

对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏。

1)比如在Activity中register了一个BraodcastReceiver,但在Activity结束后没有unregister该BraodcastReceiver。

2)资源性对象比如Cursor,Stream、File文件等往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。

3)对于资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉,然后再设置为null。在我们的程序退出时一定要确保我们的资源性对象已经关闭。

4)Bitmap对象不在使用时调用recycle()释放内存。2.3以后的bitmap应该是不需要手动recycle了,内存已经在java层了。

6、使用ListView时造成的内存泄漏

初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的View对象,同时ListView会将这些View对象缓存起来。当向上滚动ListView时,原先位于最上面的Item的View对象会被回收,然后被用来构造新出现在下面的Item。这个构造过程就是由getView()方法完成的,getView()的第二个形参convertView就是被缓存起来的Item的View对象(初始化时缓存中没有View对象则convertView是null)。

构造Adapter时,没有使用缓存的convertView。

解决方法:在构造Adapter时,使用缓存的convertView。

7、集合容器中的内存泄露

我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。

解决方法:在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。

8、WebView造成的泄露

当我们不要使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。

解决方法:为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

更多计算机相关知识,请访问常见问题栏目!

上一篇: 计算机病毒主要是造成什么破坏 下一篇: 硬盘损坏如何修复,以及如何避免硬盘损坏

推荐商品

立即预约师傅

点击预约

推荐阅读

内存泄漏的原因及解决办法是什么

本教程操作环境:windows7系统、DellG3电脑。 常见的内存泄露造成的原因1、单例造成的内存泄漏 由于单例的静态特性使得其生命周期和应用的生命周期一样长,如果一个对象已经不再需要使用了,而单例对象还持有该对象的引用,就会使得该对象....

简单到家维修服务 -2023/03/08
内存泄漏的原因及解决办法是什么

空调不开机原因是什么?空调不启动的原因及解决办法

在日常生活中不管是办公场所还是在家里,都会用到各种各样的电器,为我们工作的时候会让人感觉到无比舒服,也给生活带来了很多的便利。但是时间过长或者对电器的保养程度不

简单到家维修服务 -2020/12/18
空调不开机原因是什么?空调不启动的原因及解决办法

空调不制热的原因及解决办法是什么

随着气温的逐渐下降,使用空调制热功能成为很多人的需求。然而,有时我们会面临空调不制热的问题,让人感到苦恼。那么空调不制热的原因及解决办法是什么。

简单到家维修服务 -9天前
空调不制热的原因及解决办法是什么

地暖进水不热的原因及解决办法是什么

很多家庭都开始装上了地暖,让我们的生活带来了很多的便利,但是地暖进水不热的原因及解决办法有哪些呢?我们马上来看看相关知识吧。地暖进水不热的原因及解决办法

简单到家维修服务 -2023/09/04
地暖进水不热的原因及解决办法是什么

洗衣机不启动的原因及解决办法是什么?

洗衣机是智能时代带给我们生活的福音,它帮助我们解放双手,帮助我们清洗衣物,但是作为电器洗衣机难免会出现故障的,比如洗衣机不启动是什么原因呢?怎么解决?一起来了解一下吧。

简单到家维修服务 -2021/09/24
洗衣机不启动的原因及解决办法是什么?
首页 服务大厅 家修问答 新闻资讯 关于我们
网站地图 热门标签

备案号:渝ICP备20005664号-4

Copyright © 简单到家 cdxsxbx.com

渝公网安备 50019002503912 号

首页

电话咨询

在线客服