Android 了解堆大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10677850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Understanding Heap Sizes
提问by John P.
I'm fairly new to Android development and I can't seem to grasp the Java Out of Memory exception. I know it means that my app has gone over the VM budget but after Googling this many times I still don't seem to grasp this concept. I'm afraid that my app uses too much memory because I have six button selectors per screen with two bitmaps for each selector which are around 20 kb each according to the properties tab. On my rooted G2x I have set the VM budget to 12mb,restarted my phone and ran my app with no problems whatsoever. I am unbinding drawables on each onDestroy() and hinting at the GC to run here also. After using the app for a while in the emulator I click "Cause GC" on my DDMS screen and the results are ID=1, Heap Size 6.133 MB, Allocated 2.895MB, Free 3.238 MB, % Used 47.20, # Objects 52,623.
我对 Android 开发还很陌生,我似乎无法掌握 Java 内存不足异常。我知道这意味着我的应用程序已经超过了 VM 预算,但是在谷歌搜索了很多次之后,我似乎仍然没有掌握这个概念。我担心我的应用程序使用了太多内存,因为我每个屏幕有六个按钮选择器,每个选择器有两个位图,根据属性选项卡每个大约 20 kb。在我扎根的 G2x 上,我将 VM 预算设置为 12mb,重新启动手机并运行我的应用程序,没有任何问题。我在每个 onDestroy() 上解除绑定 drawable 并暗示 GC 也在这里运行。在模拟器中使用该应用程序一段时间后,我在 DDMS 屏幕上单击“Cause GC”,结果为 ID=1,堆大小 6.133 MB,已分配 2.895MB,空闲 3.238 MB,已使用百分比 47.20,# 对象 52,623。
This is where I dont understand what's happening, my emulator is set to 24MB of VM. Where is that number? The actual problem I'm having is that if i set the emulator to 16MB of VM my app crashes on the second activity with the Out of Memory exception. How come it doesnt crash on my phone with the VM set to 12 MB or on my old HTC Magic phone with 12 MB of VM stock? Also do you guys think my app is taking up too much memory? I have no idea if those DDMS numbers are good or not. Thanks for your time.
这是我不明白发生了什么的地方,我的模拟器设置为 24MB 的 VM。那个号码在哪里?我遇到的实际问题是,如果我将模拟器设置为 16MB 的 VM,我的应用程序会在第二个活动中崩溃,并出现内存不足异常。为什么它不会在我的 VM 设置为 12 MB 的手机上或在我的旧 HTC Magic 手机上使用 12 MB 的 VM 内存时崩溃?还有你们认为我的应用程序占用了太多内存吗?我不知道这些 DDMS 数字是否好。谢谢你的时间。
As for my code I have every image specified in XML layouts I do not do anything programmaticly with them except for adding listeners to them. I found this bit of code on here and I've added it to every activity that I have...
至于我的代码,我在 XML 布局中指定了每个图像,除了向它们添加侦听器之外,我不会以编程方式对它们执行任何操作。我在这里找到了这段代码,并将其添加到我拥有的每个活动中...
@Override
protected void onDestroy() {
super.onDestroy();
unbindDrawables(findViewById(R.id.myRootLayout));
System.gc();
}
private void unbindDrawables(View view) {
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
Otherwise all I do is add onClickListeners to the buttons that have the PNG backgrounds. I would like to learn how to specify button backgrounds programmaticly but I need to have the selector functions like on focus, on press, non-focused but pressed etc. to make the button backgrounds change according to user interaction. I have reviewed the docs about this but it seems overwhelming, that's why I figured I'd start here with the basics of managing Heaps and work my way up to specifying selectors in code. This may not make sense but is there a "healthy" amount of memory allocation that an app could allocate without getting close to the Out of Memory exception? For example if an app allocated 6MB it should be fine but 8MB would be pushing it, are there bounds like that in memory allocation? Thanks again Alex Lockwood for your response I'm going to read and re-read it again until this stuff makes sense to me
否则我所做的就是将 onClickListeners 添加到具有 PNG 背景的按钮。我想学习如何以编程方式指定按钮背景,但我需要有选择器功能,如聚焦、按下、非聚焦但按下等,以使按钮背景根据用户交互而改变。我已经查看了关于此的文档,但它似乎难以抗拒,这就是为什么我想我会从管理堆的基础知识开始,然后逐步在代码中指定选择器。这可能没有意义,但是应用程序是否可以分配“健康”的内存分配量而不会接近内存不足异常?例如,如果一个应用程序分配了 6MB 应该没问题,但 8MB 会推动它,内存分配有这样的界限吗?再次感谢 Alex Lockwood 的回复,我会反复阅读,直到这些东西对我有意义
回答by Alex Lockwood
When you set the VM budget on your emulator/device, what you are doing is telling the heap the maximum size it is allowed to be. At runtime, the heap grows dynamically in size as the Dalvik VM requests system memory from the operating system. The Dalvik VM typically starts by allocating a relatively small heap. Then after each GC run it checks to see how much free heap memory there is. If the ratio of free heap to total heap is too small, the Dalvik VM will then add more memory to the heap (up to the maximum configured heap size).
当您在模拟器/设备上设置 VM 预算时,您所做的就是告诉堆它允许的最大大小。在运行时,堆的大小随着 Dalvik VM 从操作系统请求系统内存而动态增长。Dalvik VM 通常从分配一个相对较小的堆开始。然后在每次 GC 运行后,它会检查有多少空闲堆内存。如果空闲堆与总堆的比率太小,Dalvik VM 将向堆添加更多内存(最多可配置的最大堆大小)。
That being said, the reason why you are not seeing "24 mb" on your DDMS screen is because the heap hasn't grown to its maximum size. This allows Android to make good use of the already small amount of memory that is available on handheld devices.
话虽如此,您在 DDMS 屏幕上看不到“24 mb”的原因是堆尚未增长到其最大大小。这允许 Android 充分利用手持设备上已经很少的可用内存。
As for why your application is crashing on the emulator and not your phone, that does seem odd (are you sure the numbers are correct?). You should keep in mind, however, that memory is managed dynamically and that total memory utilization is determined based on a number of external factors (the speed/frequency at which garbage collection is performed, etc.).
至于为什么您的应用程序在模拟器上崩溃而不是在您的手机上崩溃,这似乎很奇怪(您确定数字正确吗?)。但是,您应该记住,内存是动态管理的,并且总内存利用率是根据许多外部因素(执行垃圾收集的速度/频率等)确定的。
Finally, for the reasons I mentioned above, it would be difficult to say for sure how well your application manages memory based on the single line of information you provided above. We'd really need to see some of your code. OutOfMemoryError
s are definitely worth worrying about, however, so I'd definitely look into your application's memory usage. One thing you might consider is to sample your bitmap images at runtime with calls to inSampleSize
using the BitmapFactory
class. This can help reduce the amount of memory required to load your drawable bitmaps. Either that or you could reduce the resolution of your drawables (although 20 kb each sounds fine to me).
最后,由于我上面提到的原因,根据您上面提供的单行信息,很难确定您的应用程序管理内存的程度。我们真的需要看看你的一些代码。OutOfMemoryError
但是,绝对值得担心,所以我肯定会调查您的应用程序的内存使用情况。您可能会考虑的一件事是在运行时通过调用inSampleSize
usingBitmapFactory
类来对位图图像进行采样。这有助于减少加载可绘制位图所需的内存量。要么这样,要么你可以降低你的可绘制对象的分辨率(虽然每个 20 kb 对我来说听起来不错)。
回答by tbraun
Even if your application doesn't reach the "24mb" (varies within devices) heap limit you might still have crashes because Android takes a while to grow the heap space for your app.
即使您的应用程序未达到“24mb”(因设备而异)堆限制,您仍然可能会崩溃,因为 Android 需要一段时间来为您的应用程序增加堆空间。
In my situation I was creating and dumping several images in a small amount of time.
在我的情况下,我在很短的时间内创建和转储了几个图像。
Quite often I was getting OutOfMemoryError
.
我经常得到OutOfMemoryError
.
It seems Android wasn't fast enough to grow the heap space for my app.
Android 似乎不够快,无法为我的应用增加堆空间。
I believe I solved this issue by using the largeHeap
setting in the Manifest file.
With that setting on, Android leaves more free memory every time it grows the heap, minimizing the chance of hitting the current limit.
我相信我通过使用largeHeap
Manifest 文件中的设置解决了这个问题。启用该设置后,Android 每次增加堆时都会留下更多可用内存,从而最大限度地减少达到当前限制的机会。
I don't use the 24mb limit but this largeHeap
conf was quite handy.
我不使用 24mb 限制,但这个largeHeap
conf 非常方便。
You just need to set largeHeap="true"
on the application tag of your AndroidManifest.xml
你只需要largeHeap="true"
在你的应用程序标签上设置AndroidManifest.xml
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:theme="@style/AppTheme" >
Still, make sure you are carefull when dealing with images, like @Alex Lockwood advised.
尽管如此,请确保在处理图像时要小心,就像@Alex Lockwood 建议的那样。