【问题标题】:Heap not expanding on Genymotion emulator堆没有在 Genymotion 模拟器上扩展
【发布时间】:2014-10-13 21:31:33
【问题描述】:

在调整大位图的大小以便更快地将图像上传到服务器时,我偶尔会遇到 OutOfMemoryErrors。 为了防止这种情况,我在尝试缩放图像之前计算所需的内存量并检查它是否超过 Runtime.getRuntime().maxMemory()。

但是,即使图像应该可以轻松放入堆中,我仍然会遇到 OOM 错误。

模拟设备(Galaxy SII API 16)使用上述方法为我提供了 67108864 字节的最大内存。

在下面的 sn-p 中,堆大小为 43975K,并且只有

10-13 20:35:57.223: D/dalvikvm(1201): GC_FOR_ALLOC freed 505K, 67% free 14692K/43975K, paused 31ms, total 31ms
10-13 20:35:57.223: I/dalvikvm-heap(1201): Forcing collection of SoftReferences for 31961100-byte allocation
10-13 20:35:57.251: D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused 29ms, total 29ms
10-13 20:35:57.251: E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation.

我想知道这是否也可以在真实设备上发生,或者这可能是一个 genymotion 错误。

堆是否保证扩展到 maxMemory()? Runtime.getRuntime().freeMemory() 的 JavaDoc 说它“可能”扩展,无论这意味着什么。

我只需要一个可行的方法来计算我可以使用的内存量,我就是这样做的,如果我错了,请纠正我:

long maxMemory = Runtime.getRuntime().maxMemory();
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long availableMemory = maxMemory - usedMemory;

此调用导致 OutOfMemoryError:

// outOptions has an appropriate inSampleSize
BitmapFactory.decodeStream(inputStream, null, outOptions);

【问题讨论】:

  • 这个问题你解决了吗?
  • 很遗憾没有。有什么想法吗?
  • 不,很抱歉,我仍在处理它。如果我发现有帮助,我会告诉你。
  • 你是怎么分配内存的,能贴一下代码sn-p
  • 好的,我在编辑的问题中添加了代码sn-p

标签: android genymotion


【解决方案1】:

31961100 字节分配内存不足

您的位图是 32M。 VM 无法分配 32M 线性空间来存储位图。堆是碎片化的,所以即使你的堆有 32M 的可用空间,也不总是可以分配这样的线性空间。您可以尝试释放尽可能多的内存并在解码流之前调用 GC。

尝试在更多effective way 中解码您的位图。 Or process image in parts。 如果你告诉我们你为什么需要这张图片,我们可以告诉你如何处理它。

【讨论】:

  • 我已经用 inSampleSize > 1 解码位图。部分处理图像可能也不是一种选择 - 即使我可以将它保存在部分我希望会有伪影将它缝合在一起时(如果我错了,请纠正我)。我目前所做的是将图像缩小到最大边长 1920 像素,然后再将其上传到服务器。
  • 有没有办法找到可用于分配的最大连续空间?
  • 不。检查这个答案:stackoverflow.com/questions/3331527/… 你也可以创建单独的进程来缩放图像,它只对图像处理具有相同的堆大小。尝试在清单中启用 userLargeHeap 选项。或者使用流上传原始图像并在服务器端对其进行缩放。
  • 那很不幸,也许我会尝试创建另一个进程。在这种情况下捕获 OutOfMemoryError 并直接上传文件是否安全?
  • 你最好不要捕获 OutOfMemoryError 并尝试恢复。谷歌一下,有很多解释。我没有看到重用位图的任何陷阱。但请记住,单独的流程并不能 100% 保证它适合您的形象。
【解决方案2】:

您有一个 42MB 堆,其中 14MB 已使用,67% (28M) 是免费/可用的

    D/dalvikvm(1201): GC_BEFORE_OOM freed 2K, 67% free 14689K/43975K, paused ...
    E/dalvikvm-heap(1201): Out of memory on a 31961100-byte allocation.

您正在尝试分配 ~31M (not 31K) ,这大于可用的 28M,导致 OOM。

详细解释dalvikvm memory allocation log message take a look at debugging memory

android 中存在大量共享内存使用情况,以正确计算每个进程的内存使用情况refer this SO question

Android best practices on efficient bitmap memory management 可能会有所帮助

【讨论】:

  • 42MB 是堆的当前大小,但 Runtime.getRuntime().maxMemory() 给了我 64 MB。我的印象是我最多可以使用 64 兆字节,并且堆会扩展到那个大小。 StackOverflow 帖子很有趣,但它并没有真正回答如何可靠地计算我可以安全分配多少内存的问题。
【解决方案3】:

您可能会尝试调整的一件事是 ROM 的build.props 文件。

在 Genymotion 模拟器上,您可以尝试通过 root shell 执行以下操作:

cat /system/build.prop | grep dalvik 

它会显示带有 dalvik 设置的行:

dalvik.vm.heapsize=256m
dalvik.vm.lockprof.threshold=500
dalvik.vm.stack-trace-file=/data/anr/traces.txt

在我试验的模拟器上,maxmemory 也被报告为 268435456 字节。

因此,您可以尝试使用此设置。另外,请确保在 VirtualBox 的设置中分配的内存与这些值兼容。

【讨论】:

  • 我其实并不关心模拟器。我只是想知道同样的事情是否会发生在真实用户的设备上,这会很糟糕。
猜你喜欢
  • 2017-12-15
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2013-09-12
  • 1970-01-01
相关资源
最近更新 更多