Answers:
对于3.0 Honeycomb之前的版本:是,请致电 System.gc()
。
我试图创建位图,但始终出现“ VM内存不足错误”。但是,当我System.gc()
第一次打电话时,还可以。
创建位图时,Android经常会因内存不足错误而失败,并且不尝试首先进行垃圾回收。因此,调用System.gc()
,您就有足够的内存来创建位图。
如果创建对象,我认为System.gc
会在需要时自动调用,而不是用于创建位图。它只是失败。
因此,我建议System.gc()
在创建位图之前手动调用。
一般来说,在存在垃圾收集器的情况下,手动调用GC 永远不是一个好习惯。GC是围绕启发式算法组织的,当将其放在自己的设备上时效果最佳。手动调用GC通常会降低性能。
有时,在某些相对罕见的情况下,可能会发现特定的GC出错了,然后手动调用GC可能会改善性能。这是因为实际上不可能实现在所有情况下都能最佳地管理内存的“完美” GC。这种情况很难预测,并且取决于许多细微的实现细节。“好的做法”是让GC自己运行;手动调用GC是个例外,只有在实际见证了实际性能问题之后,才可以设想到此。
Bitmap.finalize()
释放非VM内存的方法)。因此,在这种情况下,您应该越过GC的头部并运行Bitmap.recycle()
或System.gc()
在适当的地方运行。但只有蜂巢前。
如果我们不能正确处理位图,则在android应用程序中内存不足是很常见的,解决该问题的方法是
if(imageBitmap != null) {
imageBitmap.recycle();
imageBitmap = null;
}
System.gc();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
imageBitmap = BitmapFactory.decodeFile(URI, options);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, 200, 200, true);
imageView.setImageBitmap(scaledBitmap);
在上面的代码中,刚刚尝试回收位图,这将使您释放已使用的内存空间,因此可能不会发生内存不足的情况。
如果仍然遇到问题,您也可以添加这些行
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;
有关更多信息,请查看此链接
注意:由于执行gc会导致短暂的“暂停”,因此不建议在每次分配位图之前执行此操作。
最佳设计是:
通过显示的代码释放不再需要的所有位图if / recycle / null
。(为此提供一种帮助方法。)
System.gc();
分配新的位图。
如果出现OutOfMemoryError错误,那么调用垃圾回收器通常为时已晚...
这是来自Android Developer的报价:
在大多数情况下,垃圾收集是由于大量的小型短期对象而发生的,某些垃圾收集器(如分代垃圾收集器)可以优化这些对象的收集,以使应用程序不会被频繁中断。不幸的是,Android垃圾收集器无法执行此类优化,因此,在性能关键代码路径中创建短期对象对于您的应用程序而言非常昂贵。
因此,据我了解,没有紧急需要致电gc。最好花更多的精力避免不必要的对象创建(例如在循环内创建对象)
我的应用程序管理大量图像,但由于OutOfMemoryError而死亡。这对我有帮助。在Manifest.xml中添加
<application
....
android:largeHeap="true">
一般来说,您不应使用System.gc()显式调用GC。甚至在IO讲座(http://www.youtube.com/watch?v=_CruQY55HOk)上,他们都解释了GC暂停日志的含义,并且在其中他们还声明从不调用System.gc(),因为Dalvik更了解比您什么时候这样做。
另一方面,如上文所述,Android中的GC流程(像其他所有流程一样)有时会出现问题。这意味着Dalvik GC算法不能与Hotspot或JRockit JVM相提并论,在某些情况下可能会出错。这些情况之一就是分配位图对象时。这是一个棘手的问题,因为它使用堆和非堆内存,并且因为内存受限设备上的一个位图对象的松散实例足以给您OutOfMemory异常。因此,许多开发人员通常建议在不再需要该位图后调用它,甚至被某些人认为是一种好习惯。
更好的做法是在位图上使用.recycle(),因为这样做是为了实现此方法,因为它将位图的本机内存标记为可以安全删除。请记住,这是非常依赖于版本的,这意味着通常在较旧的Android版本(我认为是3.0之前的版本)上是必需的,而在更高版本上则不需要。同样,在较新版本的ether上使用它也不会造成太大伤害(只是不要循环执行或类似操作)。新的ART运行时在这里发生了很大的变化,因为它们为大型对象引入了特殊的堆“分区”,但是我认为使用ART ether这样做不会有多大伤害。
也是有关System.gc()的非常重要的说明。此方法不是Dalvik(或JVM)必须响应的命令。认为它更像是对虚拟机说“如果没有麻烦,请您进行垃圾收集”。
创建位图期间避免OOM的最佳方法,
http://developer.android.com/training/displaying-bitmaps/index.html
...
GC_EXPLICIT
显式GC,例如调用gc()时(应避免调用它,而应信任GC在需要时运行)。
...
我已用黑体突出显示了相关部分。
看一下YouTube系列Android性能模式 -它会向您展示管理应用程序内存使用情况的提示(例如,使用Android的ArrayMap
和SparseArray
而不是HashMap
s)。
结束后无需调用垃圾收集器OutOfMemoryError
。
Javadoc明确指出:
Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.
因此,垃圾收集器在产生错误之前已经尝试释放内存,但是没有成功。