Android内存使用情况和内存中的对象未在1.6和2.1中发布

时间:2011-09-08 03:30:40

标签: android memory-management out-of-memory

我正在检查我的应用程序是否存在内存泄漏/使用情况,并且遇到了一些我在Android 1.6和2.1中迄今为止才看到的奇怪内容。在应用程序中点击一下后,我为我的应用程序运行“adb shell dumpsys meminfo”,我看到以下内容:

DUMP OF SERVICE meminfo:
Applications Memory Usage (kB):
Uptime: 34639912 Realtime: 153524709

** MEMINFO in pid 5778 [com.app.myapp] **
                    native   dalvik    other    total
            size:    14336     4679      N/A    19015
       allocated:    13971     4139      N/A    18110
            free:      280      540      N/A      820
           (Pss):     2986     4181    13491    20658
  (shared dirty):      972     3948      620     5540
    (priv dirty):     2876     3224    10976    17076

 Objects
           Views:      545        ViewRoots:        4
     AppContexts:       32       Activities:       31
          Assets:        2    AssetManagers:        2
   Local Binders:       43    Proxy Binders:       79
Death Recipients:        2
 OpenSSL Sockets:        1

 SQL
            heap:       91          dbFiles:        0
       numPagers:        4   inactivePageKB:        0
    activePageKB:        0

 Asset Allocations
    zip:/data/app/com.app.myapp.apk:/resources.arsc: 119K

正如你所看到的,没有任何东西被解除分配/ GC,活动堆积,AppContexts等等,直到应用程序崩溃与OutOfMemoryError。这不会发生在2.2 +。

有人能告诉我为什么会这样吗?我有一种感觉,它或者是简单的东西,或者它只是我的应用程序的奇怪之处,但我不知道为什么会发生这种情况。

仅供参考,我已经在1.6和2.1模拟器中重现了这一点,以及我的G1运行1.6。用户最近的崩溃报告也显示了这一点,他们在Droid Eris上运行2.1。如果需要更多细节/代码来帮助我,请告诉我。

## UPDATE ##

感谢momo提供的信息,我能够找到一些内存泄漏问题,这大大减少了将在meminfo的Objects列表中显示的Activities / AppContexts数量。

现在该数字已经下降到我的应用程序中的实际活动数量左右,因此在旧版本的Android上,它似乎会显示您的应用正在消耗的对象总数。在较新的版本上它不会,但这可能只是我的测试设备上的情况。

2 个答案:

答案 0 :(得分:9)

为了清楚地了解为什么要保持活动,我通常会使用MAT,然后查看来自活动卡片的GC根路径。

我创建了一个简单的项目,它加载简单的TestActivity以说明该过程。以下是代码:


package com.so;

import android.app.Activity;
import android.os.Bundle;

public class TestActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

以下是步骤:

  • 通过DDMS“转储HPROF文件”功能
  • 将hprof转储到正在运行的进程上
  • 假设你安装了MAT,这应该会调出MAT屏幕
  • 现在根据您的活动包进行过滤,对于上面的示例,它是com.so.此过程的屏幕截图如下:

MAT Histogram Screen

  • 现在您想看看它是否有明确的GC路径。您可以通过右键单击“活动”并显示所有引用来执行此操作,如下所示:

Show all references

您应该看到您的Activity由com.android.internal.policy.impl.PhoneWindow $ DecorView保留,而不是其他任何人。如果是这种情况,您就可以了,GC最终将回收此活动。

现在我将更改我的类以包含一个将保存其自己的实例的静态变量:


package com.so;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;

public class TestActivity extends Activity {
    static ArrayList memoryLeakList;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // create a deliberate static list to cause the leak
        TestActivity.memoryLeakList = new ArrayList();
        TestActivity.memoryLeakList.add(this);
    }
}

如果我用相同的步骤运行代码hprof,我现在得到的活动的引用由ArrayList保存,而不是com.android.internal.policy.impl.PhoneWindow $ DecorView表示有可能如果我不清理阵列就会泄漏

Memory Leak caused by ArrayList

现在,您不必为每个Activity执行此操作,我只需简单地运行应用程序然后转储HPROF即可。然后,您将再次按包筛选以获取应用程序的快照。在最初的直方图中,在DDMS中点击GC按钮并开始从那里进行调查后,您应该怀疑任何具有多个实例数的活动。

还有一点需要注意,在我的2.1手机上,我无法通过DDMS获得HPROF,所以我按照以下步骤通过模拟器完成了这项工作:

  • 转到./adb shell
    • 输入ps以获取应用进程的pid
    • 键入kill -10,你应该在你的logcat中看到它正在将内存转储到/ data / misc
    • 如果您获得权限被拒绝,请确保通过执行chmod 777 data / misc来读取/写入该文件夹
  • 使用Eclipse中的DDMS文件资源管理器或拉动命令
  • 拉出生成的hprof
  • 由于hprof是基于dalvik的,为了将其与内存分析工具一起使用,您需要先通过Android SDK安装的tools目录中提供的hprof-conv进行转换

    Run ./hprof-conv [source dump] [target dump]

答案 1 :(得分:0)

使用Memory Analyzer(MAT)查看您的进程堆。 http://www.eclipse.org/mat/