我正在检查我的应用程序是否存在内存泄漏/使用情况,并且遇到了一些我在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上,它似乎会显示您的应用正在消耗的对象总数。在较新的版本上它不会,但这可能只是我的测试设备上的情况。
答案 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);
}
}
以下是步骤:
您应该看到您的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表示有可能如果我不清理阵列就会泄漏
现在,您不必为每个Activity执行此操作,我只需简单地运行应用程序然后转储HPROF即可。然后,您将再次按包筛选以获取应用程序的快照。在最初的直方图中,在DDMS中点击GC按钮并开始从那里进行调查后,您应该怀疑任何具有多个实例数的活动。
还有一点需要注意,在我的2.1手机上,我无法通过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/