2

我正在 HTC Sensation OS 4.0.3 上测试我的应用程序。OutOfMemoryError当我似乎有足够的可用内存时,我很困惑为什么我在某些情况下会点击s。

例如,在这种情况下,我一直在正常使用我的应用程序。我让它无人看管了大约 5 分钟,并确认该应用程序已关闭其网络连接和处理线程。几分钟后,当我重新打开屏幕时,我立即看到一个崩溃弹出窗口出现。

我试图在下面列出看起来可能很重要的日志。

grep "GC_\|memalloc\|OutOfMemoryError" ~/trace.txt

这种特殊情况显示 130KB 字节缓冲区分配失败,而显然有 40MB 可用堆空间。我已经看到很多其他地方也出现了小分配失败,最常见的是setContentView在 onCreate 或其他一些小的 UI 操作中。

10-05 00:26:32.299 32478 32481 D dalvikvm: GC_CONCURRENT freed 4032K, 73% free 13737K/49187K, paused 3ms+28ms
10-05 00:26:38.105 32478 32481 D dalvikvm: GC_CONCURRENT freed 3812K, 73% free 13481K/49187K, paused 4ms+27ms
10-05 00:26:41.698 32478 32481 D dalvikvm: GC_CONCURRENT freed 3927K, 74% free 13122K/49187K, paused 3ms+26ms
10-05 00:26:45.802 32478 32481 D dalvikvm: GC_CONCURRENT freed 3572K, 74% free 12999K/49187K, paused 3ms+27ms
10-05 00:26:48.365 32478 32481 D dalvikvm: GC_CONCURRENT freed 3563K, 74% free 12844K/49187K, paused 3ms+26ms
10-05 00:26:53.069 32478 32481 D dalvikvm: GC_CONCURRENT freed 3506K, 75% free 12675K/49187K, paused 4ms+55ms
10-05 00:26:57.363 32478 32481 D dalvikvm: GC_CONCURRENT freed 3672K, 75% free 12303K/49187K, paused 3ms+25ms
10-05 00:27:01.447 32478 32481 D dalvikvm: GC_CONCURRENT freed 3344K, 76% free 12180K/49187K, paused 3ms+24ms
10-05 00:27:05.121 32478 32481 D dalvikvm: GC_CONCURRENT freed 3212K, 76% free 12034K/49187K, paused 4ms+69ms
10-05 00:27:10.426 32478 32481 D dalvikvm: GC_CONCURRENT freed 3267K, 76% free 11813K/49187K, paused 4ms+40ms
10-05 00:27:14.340 32478 32481 D dalvikvm: GC_CONCURRENT freed 3184K, 77% free 11578K/49187K, paused 3ms+41ms

At this point the app shuts down its various threads.  

10-05 00:35:52.545   249   410 D dalvikvm: GC_EXPLICIT freed 3223K, 50% free 17332K/34531K, paused 4ms+14ms
10-05 00:38:54.633 32478 32478 D dalvikvm: GC_FOR_ALLOC freed 2627K, 78% free 10904K/49187K, paused 113ms
10-05 00:38:54.633 32478 32478 I dalvikvm-heap: Forcing collection of SoftReferences for 131102-byte allocation
10-05 00:38:54.733 32478 32478 D dalvikvm: GC_BEFORE_OOM freed 5K, 78% free 10899K/49187K, paused 97ms
10-05 00:38:54.733 32478 32478 E dalvikvm-heap: Out of memory on a 131102-byte allocation.
10-05 00:38:54.733 32478 32478 I dalvikvm: "main" prio=5 tid=1 RUNNABLE
10-05 00:38:54.733 32478 32478 I dalvikvm:   | group="main" sCount=0 dsCount=0 obj=0x40ad3490 self=0x40f9d0
10-05 00:38:54.733 32478 32478 I dalvikvm:   | sysTid=32478 nice=0 sched=0/0 cgrp=default handle=1074746568
10-05 00:38:54.733 32478 32478 I dalvikvm:   | schedstat=( 0 0 0 ) utm=4527 stm=381 core=1
10-05 00:38:54.733 32478 32478 I dalvikvm:   at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
10-05 00:38:54.733 32478 32478 I dalvikvm:   at java.nio.MemoryBlock.allocate(MemoryBlock.java:126)
10-05 00:38:54.733 32478 32478 I dalvikvm:   at java.nio.ReadWriteDirectByteBuffer.<init>(ReadWriteDirectByteBuffer.java:46)
10-05 00:38:54.733 32478 32478 I dalvikvm:   at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:68)
10-05 00:38:54.733 32478 32478 I dalvikvm:   at de.tavendo.autobahn.WebSocketReader.<init>(WebSocketReader.java:98)
<snip>
10-05 00:38:54.743 32478 32478 I dalvikvm: 
10-05 00:38:54.743 32478 32478 E dalvikvm: Out of memory: Heap Size=49187KB, Allocated=10899KB, Limit=49152KB
10-05 00:38:54.743 32478 32478 E dalvikvm: Extra info: Footprint=49187KB, Allowed Footprint=49187KB, Trimmed=32296KB
10-05 00:38:54.743 32478 32478 W dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x40ad2228)
10-05 00:38:54.953   249   279 D memalloc: /dev/pmem: Unmapping buffer base:0x5aea5000 size:16502784 offset:14483456
10-05 00:38:54.953   249   279 D memalloc: /dev/pmem: Unmapping buffer base:0x59a63000 size:6197248 offset:4177920
10-05 00:38:54.963   112 24561 D memalloc: /dev/pmem: Freeing buffer base:0x4259d000 size:2019328 offset:4177920 fd:38
10-05 00:38:55.124 24504 24504 D dalvikvm: GC_EXPLICIT freed 367K, 41% free 3128K/5219K, paused 2ms+6ms
10-05 00:38:55.234   112   169 D memalloc: /dev/pmem: Freeing buffer base:0x42f71000 size:2019328 offset:14483456 fd:29
10-05 00:38:55.574 24504 24504 D dalvikvm: GC_EXPLICIT freed 18K, 41% free 3114K/5219K, paused 2ms+3ms
10-05 00:38:55.804 32478 32478 E Crittercism: java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=10899KB)
10-05 00:38:56.305 32478 32481 D dalvikvm: GC_CONCURRENT freed 2736K, 78% free 10851K/49187K, paused 3ms+8ms
10-05 00:38:57.256 32478  1947 D dalvikvm: JIT code cache reset in 2 ms (1048548 bytes 3/0)
10-05 00:38:57.266 32478  1947 D dalvikvm: GC_FOR_ALLOC freed 901K, 78% free 10825K/49187K, paused 80ms
10-05 00:38:57.286 32478 32478 E AndroidRuntime: java.lang.OutOfMemoryError: (Heap Size=49187KB, Allocated=10899KB)

我正在努力理解这些日志 - 任何人都可以解释为什么会发生崩溃吗?

我读过内存碎片会导致分配失败,即使总体上应该有足够的内存。有没有办法确认是否是这种情况,如果是这样,我能做些什么来应对这种情况?

GC_CONCURRENT 日志似乎表明我的代码正在执行大量分配和释放,这可能支持内存碎片理论。

  • 我的应用程序在某些时候确实会下载大量数据,例如对于一个巨大的帐户,第一次登录时它可能是 30-40MB。
  • 我们还对图像进行了很多处理,这会增加总数。仅供参考,我们使用 Volley 进行图像加载,并具有内存(可用内存的 1/8 限制)和磁盘缓存,以避免从网络重复下载。

我知道我的问题与这个问题类似,但我认为我不需要关于位图处理的建议,因为我在 OS 4.0 上,所以所有位图数据在普通堆中都是可见的(即它应该已经包含在GC_日志中行总数)。

4

3 回答 3

4

如您所见,内存不足发生在“java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:68)”上。

并根据此页面

直接缓冲区是 I/O 的最佳选择,但创建它们可能比非直接字节缓冲区更昂贵。直接缓冲区使用的内存是通过调用本机的、操作系统特定的代码来分配的,绕过标准的 JVM 堆。建立和拆除直接缓冲区可能比堆驻留缓冲区更昂贵,具体取决于主机操作系统和 JVM 实现。直接缓冲区的内存存储区域不受垃圾回收的影响,因为它们位于标准 JVM 堆之外。

因此,这回答了您的问题,即分配不在 Java 堆上,而是在一些操作系统内存空间上。

您可能需要重新查看您的 websocket 库;或者,您是否忘记正确关闭这些阅读器?

于 2013-10-05T02:09:34.453 回答
1

事实证明,根本原因是由于使用View.setTag(int, java.lang.Object)来保存视图(遵循 ViewHolder 模式)导致的严重内存泄漏。

在 OS 2.3 设备上,已知的Android 问题 18273会导致这些内存泄漏。

解决方法是改用View.setTag(java.lang.Object)

于 2013-11-19T22:11:50.423 回答
1

尝试这个

将以下内容添加到清单中的应用程序标记中

android:largeHeap="true"

希望它会帮助你。

于 2013-10-05T04:43:29.880 回答