Android中的垃圾收集器
我见过很多Android的答案,build议在某些情况下调用垃圾回收器。
在进行内存耗尽操作之前,在Android中请求垃圾收集器是否是一个好习惯? 如果不是,我是否应该只在出现OutOfMemory
错误时调用它?
在使用垃圾收集器之前,我还有其他的事情吗?
对于3.0之前的版本honeycomb :是的, 请调用 System.gc()
。
我试图创buildBitmaps,但总是得到“虚拟机内存错误”。 但是,当我第一次调用System.gc()
,它是确定的。
在创build位图时,Android通常会因为内存不足错误而失败,并且不会首先尝试垃圾收集 。 因此,调用System.gc()
,并且有足够的内存来创build位图。
如果创build对象,我认为System.gc
将被自动调用,如果需要,但不创build位图。 它只是失败。
所以我build议在创build位图之前手动调用System.gc()
。
一般来说,在存在垃圾收集器的情况下,手动调用GC 永远不是好习惯。 GC是围绕启发式algorithm组织起来的,当离开自己的设备时,这些algorithm是最好的。 手动调用GC通常会降低性能。
偶尔 ,在一些比较罕见的情况下,可能会发现一个特定的GC错误,而手动调用GC可能会改善性能。 这是因为实际上不可能实现一个“完美”的GC,它将在所有情况下优化pipe理内存。 这种情况很难预测,并取决于许多细微的实施细节。 “好的做法”是让GC自行运行; 对GC的手动呼叫是例外情况,只有在实际性能问题得到适当的certificate后才能设想。
在android应用程序中的内存不足是非常普遍的,如果我们不正确地处理位图,问题的解决scheme将是
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;
欲了解更多信息,请看这个链接
http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html
注意:由于执行gc导致暂时的“暂停”,因此不build议在每个位图分配之前执行此操作。
最佳devise是:
-
通过显示的
if / recycle / null
代码释放不再需要的所有位图 。 (做一个方法来帮助。) -
System.gc();
-
分配新的位图。
如果你得到一个OutOfMemoryError,那么调用垃圾收集器通常已经太迟了。
这里是Android开发者的引用:
大多数情况下,垃圾收集是由于大量短暂的小型对象而产生的,一些垃圾收集器(如分代垃圾收集器)可以优化这些对象的收集,从而使应用程序不会经常中断。 不幸的是,Android垃圾回收器无法执行这样的优化,因此在性能关键代码path中创build短暂对象对于您的应用程序而言成本非常高。
所以根据我的理解,没有迫切需要调用gc。 最好避免不必要的对象创build(比如在循环内创build对象)
我的应用程序pipe理大量的图像,并与一个OutOfMemoryError死亡。 这帮助了我。 在Manifest.xml中添加
<application .... android:largeHeap="true">
看来System.gc()
不适用于Art Android 6.0.1 Nexus 5x,所以我使用Runtime.getRuntime().gc();
代替。
一般来说,你不应该使用System.gc()来明确地调用GC。 甚至还有IO讲座( http://www.youtube.com/watch?v=_CruQY55HOk ),他们解释了GC暂停日志的含义,他们也声明永远不会调用System.gc(),因为Dalvik知道更好比你什么时候这样做。
另一方面,正如在上面提到的答案中提到的那样,Android中的GC过程(就像其他所有的东西一样)有时是bug。 这意味着Dalvik GCalgorithm与Hotspot或JRockit JVM不一样,在某些情况下可能会出错。 其中一种情况是分配位图对象时。 这是一个棘手的问题,因为它使用堆和非堆内存,因为内存受限设备上的一个位图对象的松散实例足以给你一个OutOfMemoryexception。 所以在你不需要这个位图之后调用它通常被许多开发者所build议,甚至被一些人认为是好的做法。
更好的做法是在位图上使用.recycle(),这是因为它将本地内存的位图标记为安全删除。 请记住,这是非常依赖版本,这意味着它通常会在较旧的Android版本(我想3.0前)需要,但将不需要在以后的版本。 也不会伤害太多使用它在新版本乙醚(只是不要在一个循环或类似的东西这样做)。 新的ART运行时间在这里改变了很多,因为它们为大对象引入了特殊的堆“分区”,但是我认为用ART ether来做这个并不会有什么大的伤害。
关于System.gc()的一个非常重要的注意事项。 这个方法并不是Dalvik(或JVM)有义务响应的命令。 考虑它更像是说虚拟机“如果不是一个麻烦,你可以做垃圾回收”。
在创build位图时避免OOM的最佳方法是,
http://developer.android.com/training/displaying-bitmaps/index.html
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.
所以,垃圾收集器已经试图释放内存之前产生的错误,但不成功。
我会说不,因为开发人员文档在内存使用状态:
…
GC_EXPLICIT
一个显式的GC,比如当你调用gc() ( 你应该避免调用 ,而是相信GC在需要的时候运行)。
…
我已经突出显示了相关部分。
看一下YouTube系列的Android性能模式 – 它会向您展示如何pipe理应用程序的内存使用情况(比如使用Android的ArrayMap
和SparseArray
来代替HashMap
)。
Xamarin开发人员快速注意事项。
如果你想在Xamarin.Android应用程序中调用System.gc()
,你应该调用Java.Lang.JavaSystem.Gc()