家修资讯 > 家电维修 > 电脑维修 > 内存泄漏的原因及解决办法是什么

找不到附近家电维修师傅?

一键下单

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

发布时间:2022-12-08 14:37:55 来源:闪电家修网 阅读量:999

本教程操作环境: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所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

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

免责声明:本网站转载内容均来自网络,若涉及侵权请务必联系删除,本网站转载内容均来自网络,若涉及侵权请务必联系删除,本网站转载内容均来自网络,若涉及侵权请务必联系删除。
相关标签:

推荐服务

更多...
电视安装(86吋及以上)

电视安装(86吋及以上) 已售:8259

30元/起 立即预约

热门问答

更多...
家用空调不制冷的原因及解决办法
原因可能是氟利昂已经不够使用的量,可以通过补加氟利昂的方式解决;原因可能是给空调供电的电压太低,可以通过安装稳压器等办法保持电压的稳定性;原因可能是外 已有 1个问答

2023-03-01 14:47:56

海尔空调不制冷的原因及解决办法
原因可能是:氟利昂不够(又称“雪种”不够)。这属于正常的情况,一般是出现在使用三至四年的老空调,空调不是完全不制冷,而是制冷的效果不够好,这是因为老式 已有 1个问答

2023-03-01 14:43:31

断电重启后空调不制冷的原因及解决办法
一,检查空调的滤网,如果空调启动正常,但不能驱散冷空气,很可能是滤网灰尘太多,最好用那种专用的过滤器剂喷一下进行清洗。二,检查空调风扇的运行情况,如果 已有 1个问答

2023-03-01 14:31:47

变频空调不制冷的原因及解决办法
1、可能是由于室外机周围的温度过高而引起,室外机安装在较为封闭的空间,这样不利于空气的流通,会导致变频空调不制冷。2、也有可能是由于没有定期清洗变频空调 已有 1个问答

2023-03-01 14:26:59

宝马5系空调不制冷的原因及解决办法
原因是因为缺少制冷剂,这是所以空调都会面临的问题,可以通过从低压侧添加制冷剂解决;原因是因为空调翻板损坏,可以找专业的修理人员修理或在空调系统低压侧的 已有 1个问答

2023-03-01 14:26:52

精选
优选
为你
推荐
自助
下单
客服
顶部
扫码关注公众号

扫码关注公众号

 

7X24小时报修热线

扫码下单享立减

扫码下单享立减

 

全国免费报修热线

-->