22

アプリケーションでメモリ リークが発生しています。私が最初にメモリ リークを疑ったのは、ボタンを押して新しいActivity. を使用DDMSしてダンプした後.hprof file、このファイルをEclipse Memory Analyzer

円グラフに示されているように、メモリ リークの可能性が 3 つあります。 ここに画像の説明を入力

そしてメモリリークの説明:

容疑者1

「」によってロードされた「android.widget.LinearLayout」の 122 個のインスタンスは、29 585 384 (38,74%) バイトを占有します。

最大のインスタンス:

•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. 

容疑者2

「」によってロードされた「android.widget.FrameLayout」の 15 インスタンスは、29 405 016 (38,51%) バイトを占有します。

最大のインスタンス:

•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. 

容疑者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. 

私が最初に考えたのは、R.javaファイルを調べることでした。メモリ リークの可能性を示す 16 進参照がいくつか見られたからです。R.javaEclipse Memory Analyzer から 16 進文字列を検索しようとしましたが、ファイル内のアドレスが見つかりませんでした。

次に、ドミネーター ツリーを調べた結果が次のとおりです。 ここに画像の説明を入力

これはリストの最初のエントリにすぎませんが、これが最大のエントリです。

この情報を基に、メモリ リークを追跡する方法についてヒントをくれる人はいますか? この投稿に追加情報を追加する必要がある場合は、コメントを追加してください。

前もって感謝します。

編集

問題は Base クラスにある可能性があります。すべてのアクティビティはこのクラスから継承されます。このクラスの仕事は、左上隅に SlidingMenu を設定することです。これは、このクラスのコードです:

 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); 
        }
    }

私の他のアクティビティでは、この setTab メソッドは次のように呼び出されます。

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

ホーム レイアウトは次のようになります。

<?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>
4

1 に答える 1

9

大きなリソースをキャッシュするために静的変数を使用していますか?
はいの場合、アクティビティ コンテキストを使用してそのようなリソースをロードするのは、Android アプリでよくある間違いです。これにより、アクティビティとそのすべてのリソースが維持されますが、それらはもはや必要ありません。
これを修正するには、アプリケーション コンテキストを使用してそのようなリソースをロードします。

詳細については、このAndroid 開発者のブログ投稿を参照してください。

于 2012-11-21T10:47:37.023 に答える