在Android应用程序内存泄漏 [英] Memory Leaks in Android application

查看:244
本文介绍了在Android应用程序内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的经历在我的应用程序的一些内存泄漏。我第一次怀疑是内存泄漏,当我通过敲击按钮来启动一个新的活动压力测试我的应用程序。使用后 DDMS 和倾倒了 .hprof文件,这个文件我打开与的Eclipse内存分析器

我有三个可能的内存泄漏,在一个饼图显示:

和对内存泄漏的描述:

犯罪嫌疑人1

android.widget.LinearLayout,由装122实例占据29 585 384(38,74%)字节。

最大的实例:

 •android.widget.LinearLayout @ 0x4258c008  -  2 268 848(2.97%)个字节。
•android.widget.LinearLayout @ 0x425c8688  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x425e3988  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x4296e198  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x429d3aa8  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x42a10c78  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x448a1f10  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x44a65d58  -  2 268 848(2.97%)字节。
•android.widget.LinearLayout @ 0x42a14098  -  2 268 824(2.97%)字节。
•android.widget.LinearLayout @ 0x4258bd30  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x425c83b0  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x425ddff8  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x4296df80  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x42a109a0  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x42a13dc0  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x448a1c38  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x448cc338  -  999 528(1.31%)字节。
•android.widget.LinearLayout @ 0x44a65a80  -  999 528(1.31%)字节。
 

可疑2

android.widget.FrameLayout,15所载入的实例占据29 405 016(38,51%)字节。

最大的实例:

 •android.widget.FrameLayout @ 0x4245b490  -  3 266 728(4.28%)个字节。
•android.widget.FrameLayout @ 0x4247a330  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x425aa1d8  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x425df8b0  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x425efe68  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x42627590  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x42987a70  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x4299df20  -  3 266 728(4.28%)字节。
•android.widget.FrameLayout @ 0x448b6f28  -  3 266 728(4.28%)字节。
 

犯罪嫌疑人3

 的java.lang.Class,2 682情况下,通过加载<系统类加载器>中占据8 662 744(11,34%)字节。

最大的实例:

•类android.content.res.Resources @ 0x41a4f708  -  7 485 176(9,80%)字节。
 

我的第一个念头是看在 R.java 文件,因为我可以看到一些十六进制提到了可能的内存泄漏。我尝试了十六进制字符串从Eclipse的内存分析器后进行搜索,但我找不到在 R.java 文件中的地址。

接着,我期待在支配树,这就是结果:

这是仅在列表中的第一项,但是这是最大的一个。

通过这些信息,任何人可以给我如何我可以跟踪内存泄漏的提示?添加评论,如果我需要更多的信息添加到这个职位。

在此先感谢。

修改

该问题可能是在我的基类。所有活动inherites从这个类。这个班的工作就是建立一个SlidingMenu,在左上角。这是code这个类:

 公共类基地扩展活动实现OnSlideMenuItemClickListener {

        公共SlideMenu slidemenu;
        的ImageButton B:
        时间t;

        BluetoothCommunicator btCom;
        BroadcastReceiver的btBroadCaster;
        MonitorBluetoothState bluetoothState;


        公共无效setTab(INT ID){
            的setContentView(ID);
            overridePendingTransition(R.anim.activityfade,R.anim.activityfadeout);
            slidemenu =(SlideMenu)findViewById(R.id.slideMenu);
            slidemenu.init(这一点,R.menu.slide,对此,450);
            slidemenu.setHeaderImage(getResources()getDrawable(R.drawable.ic_launcher));


            B =(的ImageButton)findViewById(R.id.BtnSlide);
            b.setOnClickListener(新OnClickListener(){

                公共无效的onClick(视图v){
                    slidemenu.show();

                }
            });

            b.setOnTouchListener(新OnTouchListener(){

                @覆盖
                公共布尔onTouch(视图V,MotionEvent事件){

                    开关(event.getAction()){

                    案例MotionEvent.ACTION_DOWN:
                        b.setImageResource(R.drawable.lincolor);
                        打破;
                    案例MotionEvent.ACTION_UP:
                        b.setImageResource(R.drawable.lin);
                        打破;
                    }
                    返回false;
                }
            });
        }

        @覆盖
        公共无效onSlideMenuItemClick(INT的itemId){

            类<> CLS = NULL;

            开关(的itemId){
            案例R.id.item_one:
                CLS = Home.class;
                打破;
            案例R.id.item_two:
                CLS = History.class;
                打破;
            案例R.id.item_three:
                CLS = ClearHistoryDialog.class;
                打破;
            案例R.id.item_four:
                CLS = SendLogDialog.class;
                打破;
            案例R.id.item_five:
                CLS = PasswordDialog.class;
                打破;
            案例R.id.item_six:
                CLS = About.class;
                打破;
            }
            意向意图=新的意图(这一点,CLS);
            startActivity(意向);
        }
    }
 

在我的其他活动,这setTab方法将被称为是这样的:

 公共类主要扩展基地{
        公共无效的onCreate(包B){
          super.onCreate(B);
          super.setTab(R.layout.Home);
        }
    }
 

当家居布置是这样的:

 < XML版本=1.0编码=UTF-8&GT?;
< RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@ + ID /母
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT
    机器人:后台=#e4e8ed
    机器人:重力=顶>

    <的LinearLayout
        的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        机器人:ID =@ + ID /第一
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:方向=垂直
        机器人:填充=0px​​>

        <包括
            机器人:ID =@ + ID /的TabBar
            布局=@布局/标签/>

        < com.workspace.tobias
            机器人:ID =@ + ID / slideMenu
            机器人:layout_width =match_parent
            机器人:layout_height =match_parent/>

        <按钮
            机器人:ID =@ + ID / NIST
            机器人:layout_width =match_parent
            机器人:layout_height =67dp
            机器人:layout_gravity =center_horizo​​ntal
            机器人:layout_marginBottom =3DP
            机器人:layout_marginLeft =3DP
            机器人:layout_marginRight =3DP
            机器人:layout_marginTop =3DP
            机器人:背景=@可绘制/就绪
            机器人:文字颜色=#FFFFFF/>

        <的ListView
            机器人:ID =@ + ID / lastCases
            机器人:layout_width =FILL_PARENT
            机器人:layout_height =FILL_PARENT/>
    < / LinearLayout中>


    <的LinearLayout
        的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        机器人:ID =@ + ID /加载
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_centerHorizo​​ntal =真
        机器人:layout_marginTop =300dp
        机器人:方向=横向>

        <进度
            机器人:ID =@ + ID /进步
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT
            机器人:不确定=真/>

        <的TextView
            机器人:ID =@ + ID / loadingCases
            机器人:layout_width =match_parent
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_gravity =center_vertical
            机器人:文本=@字符串/加载
            机器人:文字颜色=#707070
            机器人:TEXTSIZE =18dp
            机器人:layout_marginLeft =10dp/>
    < / LinearLayout中>

< / RelativeLayout的>
 

解决方案

你使用静态变量缓存大的资源?
如果是的话那么这是一个常见的​​错误的Andr​​oid应用程序使用的活动范围内加载这些资源。 这导致维持活动和所有的资源,即使它们不需要任何更多。
为了解决这个问题使用应用程序上下文来加载这些资源!

您可以参考这个 Android开发者博客文章了解详细信息。

I'm experience some memory leaks in my application. The first time I suspected the memory leak was when I stress-tested my application by hitting a button to start a new Activity. After using DDMS and dumping out a .hprof file, this file I opened with the Eclipse Memory Analyzer

I got three possible Memory Leaks, shown in a Pie chart:

And a description to the Memory Leaks:

Suspect 1

122 instances of "android.widget.LinearLayout", loaded by "" occupy 29 585 384 (38,74%) bytes.

Biggest instances:

•android.widget.LinearLayout @ 0x4258c008 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x425c8688 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x425e3988 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x4296e198 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x429d3aa8 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x42a10c78 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x448a1f10 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x44a65d58 - 2 268 848 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x42a14098 - 2 268 824 (2,97%) bytes. 
•android.widget.LinearLayout @ 0x4258bd30 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x425c83b0 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x425ddff8 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x4296df80 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x42a109a0 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x42a13dc0 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x448a1c38 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x448cc338 - 999 528 (1,31%) bytes. 
•android.widget.LinearLayout @ 0x44a65a80 - 999 528 (1,31%) bytes. 

Suspect 2

15 instances of "android.widget.FrameLayout", loaded by "" occupy 29 405 016 (38,51%) bytes.

Biggest instances:

•android.widget.FrameLayout @ 0x4245b490 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x4247a330 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x425aa1d8 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x425df8b0 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x425efe68 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x42627590 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x42987a70 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x4299df20 - 3 266 728 (4,28%) bytes. 
•android.widget.FrameLayout @ 0x448b6f28 - 3 266 728 (4,28%) bytes. 

Suspect 3

2 682 instances of "java.lang.Class", loaded by "<system class loader>" occupy 8 662 744 (11,34%) bytes. 

Biggest instances:

•class android.content.res.Resources @ 0x41a4f708 - 7 485 176 (9,80%) bytes. 

My first thought was to look in the R.java file, because I could see some hex references to the possible memory leak. I tried to search after the hex-string from Eclipse Memory Analyzer, but I couldn't find the addresses in the R.java file.

Then I looked in the Dominator Tree, and this is the result:

This is only the first entry in the list, but this is the biggest one.

With this information, can anybody give me a hint on how I can track the Memory Leak? Add a comment if I need to add additional information to this post.

Thanks in advance.

EDIT

The problem may be in my Base class. All the Activities inherites from this class. This classes job is to set up a SlidingMenu, in the left upper corner. This is the code for this class:

 public class Base extends Activity implements OnSlideMenuItemClickListener {

        public SlideMenu slidemenu;
        ImageButton b;
        Time t; 

        BluetoothCommunicator btCom; 
        BroadcastReceiver btBroadCaster;
        MonitorBluetoothState bluetoothState;


        public void setTab(int id) {
            setContentView(id);
            overridePendingTransition(R.anim.activityfade, R.anim.activityfadeout);
            slidemenu = (SlideMenu) findViewById(R.id.slideMenu);
            slidemenu.init(this, R.menu.slide, this, 450);
            slidemenu.setHeaderImage(getResources().getDrawable(R.drawable.ic_launcher));


            b = (ImageButton) findViewById(R.id.BtnSlide);
            b.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    slidemenu.show();

                }   
            });

            b.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {

                    switch (event.getAction()) {

                    case MotionEvent.ACTION_DOWN:
                        b.setImageResource(R.drawable.lincolor);
                        break;
                    case MotionEvent.ACTION_UP:
                        b.setImageResource(R.drawable.lin);
                        break;
                    }
                    return false;
                }
            });
        }

        @Override
        public void onSlideMenuItemClick(int itemId) {

            Class<?> cls = null; 

            switch(itemId) {
            case R.id.item_one:
                cls = Home.class;
                break;
            case R.id.item_two:
                cls = History.class;
                break;
            case R.id.item_three:
                cls = ClearHistoryDialog.class;
                break;
            case R.id.item_four:
                cls = SendLogDialog.class;
                break;
            case R.id.item_five:
                cls = PasswordDialog.class;
                break;
            case R.id.item_six:
                cls = About.class; 
                break;
            }
            Intent intent = new Intent(this, cls); 
            startActivity(intent); 
        }
    }

In my other Activities, this setTab method will be called like this:

    public class Main extends Base {
        public void onCreate(Bundle b) {
          super.onCreate(b);
          super.setTab(R.layout.Home);
        }
    }

Where the Home Layout is like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#e4e8ed"
    android:gravity="top" >

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/first"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="0px" >

        <include
            android:id="@+id/tabBar"
            layout="@layout/tab" />

        <com.workspace.tobias
            android:id="@+id/slideMenu"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <Button
            android:id="@+id/nist"
            android:layout_width="match_parent"
            android:layout_height="67dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="3dp"
            android:layout_marginLeft="3dp"
            android:layout_marginRight="3dp"
            android:layout_marginTop="3dp"
            android:background="@drawable/ready"
            android:textColor="#FFFFFF" />

        <ListView
            android:id="@+id/lastCases"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </LinearLayout>


    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="300dp"
        android:orientation="horizontal" >

        <ProgressBar
            android:id="@+id/progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true" />

        <TextView
            android:id="@+id/loadingCases"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="@string/Loading"
            android:textColor="#707070"
            android:textSize="18dp"
            android:layout_marginLeft="10dp" />
    </LinearLayout>

</RelativeLayout>

解决方案

Do you use static variables to cache big resources?
If yes then that's a common mistake in Android apps to use activity context to load such resources. This leads to sustain activities and all their resources even though they are not needed any more.
To fix this use application context to load such resources!

You can refer to this Android developers blog post for more details.

这篇关于在Android应用程序内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆