Android 内存使用情况以及内存中的对象在 1.6 和 2.1 中未释放

发布于 2024-12-03 12:03:03 字数 1680 浏览 0 评论 0原文

我正在检查我的应用程序的内存泄漏/使用情况,发现了一些奇怪的东西,到目前为止我只在 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 模拟器以及运行 1.6 的 G1 中重现了这一点。一位用户最近的崩溃报告也显示了这一点,他们在 Droid Eris 上运行 2.1。如果需要更多详细信息/代码来帮助解决此问题,请告诉我。

##UPDATE##

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

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

I'm checking my app for Memory Leaks/Usage and came across something weird that I've only seen so far in Android 1.6 and 2.1. After clicking around in the app a bit and I run "adb shell dumpsys meminfo" for my application, I see the following:

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

As you can see, nothing is getting deallocated/GC'd, the Activities are piling up, the AppContexts, etc. until the app just crashes with an OutOfMemoryError. This doesn't happen on 2.2+.

Can anybody give me some insight into why this is happening? I have a feeling it's either something simple, or it's just something weird with my app, but I'm at a loss as to why this is happening.

FYI, I've reproduced this in a 1.6 and 2.1 emulator, as well as my G1 running 1.6. A recent crash report from a user also shows this, which they were running 2.1 on a Droid Eris. Let me know if any more details/code is needed to help with this.

##UPDATE##

Thanks to the info from momo, I was able to track down some memory leak issues, which drastically cut down on the amount of Activities/AppContexts that would show in the Objects list of meminfo.

The number is now down to around the number of actual activities that are in my application, so it seems that on older versions of Android, it will show the total amount of objects your app is consuming. On newer versions it won't, though that could just be only the case on my test devices.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

活泼老夫 2024-12-10 12:03:03

为了清楚地了解 Activity 被阻止的原因,我通常使用 MAT,然后查看卡住的 Activity 到 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 路径。您可以通过右键单击“活动”并显示所有引用来完成此操作,如下所示:

显示所有引用

您应该看到您的活动是由 com.android.internal.policy.impl.PhoneWindow$DecorView 持有,没有其他人持有。如果是这种情况,没关系,这个 Activity 最终会被 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,我现在得到的 Activity 的引用由 ArrayList 而不是 com.android 保存.internal.policy.impl.PhoneWindow$DecorView 表示如果我不清理数组,就有可能发生泄漏

现在,您不必对每个 Activity 都这样做,我要做的只是简单地运行应用程序,然后转储 HPROF。然后,您将再次按包进行过滤以获取应用程序的快照。在初始直方图中,您应该对在 DDMS 中点击 GC 按钮后实例数量超过 1 的任何活动表示怀疑,并从那里开始调查。

还要注意的是,在我的 2.1 手机上,我无法通过 DDMS 获取 HPROF,因此我按照以下步骤通过模拟器进行操作:

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

    运行 ./hprof-conv [源转储] [目标转储]

To get a clear picture on why Activities are held up, I normally use MAT and then look at Path to GC root from the Activity that get stuck.

I've a created a simple project which load simple TestActivity in order to illustrate the process. Below is the code for it:


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

Here are the steps:

  • Dump the hprof on the running process via DDMS "Dump HPROF File" function
  • Assuming you have MAT installed, this should bring up the MAT screen
  • Now filter based on your activity package, for the sample above, it is com.so. Screenshot for this process is below:

MAT Histogram Screen

  • Now you want to see if this has a clear path to GC. You do that by right clicking the Activity and show all references as shown below:

Show all references

You should see that your Activity is held by com.android.internal.policy.impl.PhoneWindow$DecorView and no one else. If this is the a case, you are ok and this Activity will be eventually reclaimed by GC.

Now I will do change my class to include a static variable that will hold its own instance:


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

And if I run the code hprof with the same steps, I now get the reference of the Activity is held by the ArrayList and not the com.android.internal.policy.impl.PhoneWindow$DecorView signifying that there is possibility of a leak if I don't clean up the array

Memory Leak caused by ArrayList

Now, you don't have to do that for every Activity, what I would do just briefly run the app and then dump the HPROF. You would then again filter by package to get the snapshot of your application. In the initial Histogram, you should be suspicious for any Activity that has number of instances more than one after hitting GC button in DDMS and start investigating from there.

One more note, on my 2.1 phones, I couldn't get the HPROF via DDMS, so I did it through the emulator following these steps:

  • Go to ./adb shell
    • Type ps to get the pid of your app process
    • Type kill -10 , you should see in your logcat that it is dumping the memory to /data/misc
    • If you get permission denied, make sure you read/write on that folder by doing chmod 777 data/misc
  • Pull the hprof generated by either using DDMS File Explorer in Eclipse or pull command
  • Since the hprof is dalvik based, in order to use it with memory profiling tools you need to convert it first via hprof-conv available in the tools directory of your Android SDK installation

    Run ./hprof-conv [source dump] [target dump]
迟月 2024-12-10 12:03:03

使用内存分析器 (MAT) 查看您的进程堆。
http://www.eclipse.org/mat/

Use Memory Analyzer (MAT) to view your process Heap.
http://www.eclipse.org/mat/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文