当前位置:首页 > 内存 > 正文

android内存泄露的根本原因(android怎么检测内存泄露)

  • 内存
  • 2024-05-28 03:58:20
  • 5019

一、常见的内存泄露有哪些android1.在不关闭游标的情况下查询数据库
在Android中,游标是一个常用的对象,但是在编写代码时,人们经常忘记调用闭包,或者由于代码逻辑问题而没有调用闭包。
通常,在Activity中,我们可以调用startManagingCursor或者直接使用ManagedQuery来让Activity自动管理游标对象。
但是需要注意的是,提交activity后,光标将不再可用!
如果运行光标的代码与UI不同步(比如后台线程),则不需要先判断activity是否已经完成,或者等待后台线程完成后再调用OnDestroy。
此外,以下也是常见的游标未关闭的情况:
{
c=queryCursor();/>=(1);
4.......
();
6.}catch(Exceptione){
7.
虽然看起来调用了(),但如果发生异常,就会跳过Close(),导致内存泄漏。
所以,我们的代码应该这样写:
c=queryCursor();
{
=c。getInt(1);
04....
05.}catch(Exceptione){
06.}最后{
07.c.关闭();//最后调用close(),确保会被调用
08.
2.调用RegisterReceiver后,不会调用unregisterReceiver()。
调用RegisterReceiver后,如果不调用unregisterReceiver,则说明其占用内存过大。
我们经常可以看到类似下面的代码:
erReceiver(newBroadcastReceiver(){
02....
03.},filter);...
这是一个非常严重的错误,因为它会导致BroadcastReceiver无法注销并导致内存泄漏。
tream/OutputStream不关闭
使用文件或者访问网络资源时,使用InputStream/OutputStream也可能会导致内存泄漏
4.使用Bitmap后没有调用Recycle()
根据SDK的描述,调用recycle并不是必须的。但在实际使用中,bitmap会占用大量内存,所以当我们不再使用它时,尝试调用recycle()来释放资源。
5.上下文泄漏
这是一个非常神秘的内存泄漏案例。
我们先看一下下面的代码:
estaticDrawablesBackground;
02.
03.@Override
tedvoidonCreate(Bundlestate){
te(state);
06.
ewlabel=newTextView(this);
t("Leaksarebad");
09.
(sBackground==null){
round=getDrawable(_bitmap);
12.
kgroundDrawable(sBackground));
14.
tentView(label);
16.
在此代码中,我们使用静态可绘制对象。
这种情况通常发生在我们需要重复调​​用Drawable,并且加载时间较长,并且我们不希望每次加载activity时都创建这个Drawable的时候。
此时,使用不变性无疑是编写代码最快的方式,但同时也是非常糟糕的。
当Drawable附加到View时,View将被设置为Drawable的回调(通过调用lback())。
这意味着这个Drawable有对TextView的引用,而TextView有对Activity的引用。
这会导致Activity销毁后内存没有被释放。
二、android什么会造成内存泄露

没有人喜欢OutOfMemoryError

在Square的注册过程中,我们将用户的签名绘制在位图上。这个位图大约是设备屏幕的大小,在创建它时,我遇到了大量的OOM崩溃。

我们尝试了多种方法,但都没有解决我们的问题:

使用_8(签名不需要颜色)


我们看待问题的方式是错误的

位图本身的大小不是问题。当内存快满的时候,随时随地都可能发生OOM。创建大型对象(例如位图)时最有可能发生这种情况。OOM通常代表一个更深层次的问题:内存泄漏。

什么是内存泄漏?

有些对象的生命周期是有限的。当他们的工作完成后,他们就会被收集垃圾。如果一个对象在其生命周期应该结束时仍然被一系列引用所引用,这将导致内存泄漏。随着泄漏的累积,应用程序将耗尽内存。

例如,在调用roy()后,显示树和关联的位图应该被垃圾收集。如果正在运行的后台线程继续持有对此Activity的引用,则关联的内存将不会被回收,这最终将导致OutOfMemoryError崩溃。

查找内存泄漏

查找内存泄漏是一个手动过程,Raizlabs的WranglingDalvik系列中有明确描述。

以下是主要步骤:

通过Bugsnag、Crashlytics或DeveloperConsole了解OOM

主动重现问题。您可能需要购买、借用或窃取一个会崩溃的特殊设备(并非所有设备都会发生内存泄漏!)。您还需要知道哪些字符串会导致内存泄漏。

发生OOM时清空堆(具体做法如下)。

使用MAT或YourKit内存跟踪工具来跟踪内存变化并找出哪些对象应该是垃圾

推断从对象到GCroots的最短强引用路径;

查找路径中不存在的引用,修复内存泄漏;

如果有一个库可以为您完成所有工作,让您专注于修复内存泄漏,那就太好了。

LeakCanary简介

LeakCanary是一个开源Java库,用于检测调试版本中的内存泄漏。

让我们看一个Paint的示例:


classPaint{

}

classBox{

CathiddenCat;

}

classDocker{

静态Box容器;

}

//...

Boxbox=newBox();

CatschrodingerCat=newCat();

Cat=schrodingerCat;

ner=box;

创建RefWatcher的一个实例,然后给出要监视的对象:


//我们预计schrodingerCat很快就会消失(或不会),让我们观察它。


(schrodingerCat);

当检测到泄漏时,您将自动获得一个不错的泄漏指示器:


*GCROOT静态ner

*引用Cat

*泄漏Cat实例

我们知道您的时间很宝贵。所以我们让它非常容易设置。只需几行代码,LeakCanary就可以自动检测Activity泄漏:


publicclassExampleApplicationextendsApplication{

@OverridepublicvoidonCreate(){

te();

l(this);

}

}

内存不足时会有提示,并有良好的显示界面:

结论

启用AfterLeakCanary后,我们发现并修复了许多内存泄漏。我们还在AndroidSDK中发现了一些漏洞。

结果令人惊叹,现在我们已将OOM崩溃减少了94%。

如果您想结束OOM崩溃,请立即安装LeakCanary