Android内存泄漏?

16

我认为我的Android应用程序存在内存泄漏问题。虽然我不完全确定这是否是问题所在。

有时候,当打开应用程序时,它会崩溃,并且logcat显示一个“out of memory”异常,试图加载位图图像。

崩溃后,我重新打开应用程序,它可以正常工作。Logcat显示了许多“gc”,并且每隔一段时间JIT表会向上调整大小,直到应用程序因内存不足错误而崩溃。

这听起来像内存泄漏吗?如果是,我该如何找到并关闭泄漏?

这是我应用程序的adb shell meminfo。

** MEMINFO in pid 2691 [com.example.deepcliff] **
                    native   dalvik    other    total
            size:    23264     8839      N/A    32103
       allocated:    12503     3826      N/A    16329
            free:      168     5013      N/A     5181
           (Pss):     2512     1395    13815    17722
  (shared dirty):     2088     1844     5008     8940
    (priv dirty):     2412      224    11316    13952

 Objects
           Views:        0        ViewRoots:        0
     AppContexts:        0       Activities:        0
          Assets:        2    AssetManagers:        2
   Local Binders:       55    Proxy Binders:       13
Death Recipients:        1
 OpenSSL Sockets:        0

 SQL
               heap:      129         MEMORY_USED:      129
 PAGECACHE_OVERFLOW:        9         MALLOC_SIZE:       50

 DATABASES
      pgsz     dbsz   Lookaside(b)  Dbname
         1       14             10  webview.db
         1        6             18  webviewCache.db

 Asset Allocations
    zip:/data/app/com.example.deepcliff-2.apk:/resources.arsc: 17K

首先 - 我假设您的应用程序在新启动的设备上可以加载它所需的所有位图,当您使用它时。如果您在活动堆栈中返回几次,则会导致崩溃吗?在这种情况下,您很可能通过保留对已销毁的活动实例的引用来泄漏内存。 - Jens
1
  1. 是的,它通常运行良好。只有在我使用一段时间后关闭并重新打开它时才会崩溃。因此,如果是您提到的泄漏问题,我应该在哪里查找对我的活动实例的引用?
- Arjun
我很好奇在某些活动中频繁更改方向是否会有任何影响?这将缩小潜在的错误案例。 - Jarno Argillander
1
我不允许更改方向。它始终是垂直的。 - Arjun
1
如果可能的话,我们能看到发生“内存不足”异常的类吗?新的视角可能会在那里发现一些问题。 - Jarno Argillander
显示剩余2条评论
4个回答

33
以下是几篇文章和帖子,可能会帮助您找到正确的方向:
- Allocation tracker是Android SDK自带的工具,非常有用。阅读 Romain Guy 的文章。它帮助我找到了相当严重的泄漏问题。它还可以帮助您编写更好的软件。例如,我学会了创建较少的对象,使用更多的StringBuilder,并缓存更多内容:
何种Android工具和方法最适合查找内存/资源泄漏? - 有时您的应用程序混乱不堪,必须重新设计整个应用程序。这里提供了官方的良好提示(我最喜欢的是避免创建不必要的对象):
http://developer.android.com/guide/practices/design/performance.html - 这是一篇关于解决内存问题的优秀文章:
http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html - 官方文章关于避免内存泄漏:
http://android-developers.blogspot.co.uk/2009/01/avoiding-memory-leaks.html - 还可以阅读这个: 用于检查Android内存泄漏的工具 - 其他已经提到了位图。这里有一篇关于该问题的文章: http://zrgiu.com/blog/2011/01/android-bitmaps-and-out-of-memory-errors/

代码是否将任何活动或可绘制对象存储到静态变量中?或者它们中的任何一个存储在创建它们的类之外?当尝试优化内存消耗或分配时,很容易泄漏大量内存。例如,在创建活动时将位图存储到静态变量中。然后,在每次方向更改时,应用程序都会泄漏内存。 - Jarno Argillander
我不这么认为,至少不是有意的。我会再次检查我的代码。谢谢你提供的链接。 - Arjun
好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia

2

这不是内存泄漏。安卓设备只有有限的内存,你的位图可能太大了。你需要找到一种减小位图大小的方法。因为你没有提供更多信息,所以我无法告诉你更多。


3
这与讨论有些不相关,但是你不应该在移动应用程序中添加启动画面,这很可能会让用户感到非常烦恼。 - Kurtis Nusbaum
2
@Kurtis:我倾向于同意,但我也看到了启动画面有合理用途的情况。例如,当应用程序启动需要很长时间时。像愤怒的小鸟在我的手机上那样显示一个空白黑屏15秒钟,还不如显示一个启动画面。 - Jarno Argillander
1
@JarnoArgillander 很好。我完全同意移动游戏是一个完全不同的领域。在移动游戏中,你可以做很多其他应用程序所不能做的事情。 - Kurtis Nusbaum
好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia
@RuchirBaronia 我不知道。你应该提出一个新问题,并提供有关问题的完整细节。 - Kurtis Nusbaum
显示剩余3条评论

2

应用程序VM堆大小的典型值为24 MB。例如,如果您的图像是10Mpx(3600 x 2400),则它将分配3600 x 2400 x 4 = 34'560'000字节,这将导致OutOfMemoryError错误。


@Arjun:这已经是在RAM中有6.8 MB的位图了。一些旧设备只有16 MB的VM堆限制。 - Vit Khudenko
好的,让我来看看如何缩小它的大小。你从哪里得到了“4”的乘数? - Arjun
1
你的代码中是否有需要清理的对象或对象引用?如果你不再使用它们,或者暂时不需要使用它们,应该将它们设置为null,以释放内存。 - Bryan
1
@Arjun:每个像素的“4”倍增量是ARGB数据。同时确保不要将任何与该位图相关的内容静态地保留。 - Vit Khudenko
好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia
显示剩余2条评论

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接