Android中的垃圾收集器

hpi*_*que 105 java android garbage-collection

我见过很多Android答案,建议在某些情况下调用垃圾收集器.

在进行需要大量内存的操作之前,在Android中请求垃圾收集器是一个好习惯吗?如果没有,如果我收到OutOfMemory错误,我应该只调用它吗?

在使用垃圾收集器之前还有其他我应该使用的东西吗?

小智 141

对于3.0蜂窝之前的版本:是的,请致电 System.gc().

我试图创建Bitmaps,但总是得到"VM内存不足错误".但是,当我System.gc()第一次打电话时,没关系.

在创建位图时,Android通常会因内存不足错误而失败,并且不会首先尝试进行垃圾回收.因此,调用System.gc(),并且您有足够的内存来创建位图.

如果创建对象,我认为System.gc如果需要将自动调用,但不会创建位图.它失败了.

所以我建议System.gc()在创建位图之前手动调用.

  • 这是因为预蜂窝位图数据未存储在VM中,因此不会触发GC.它应该不是Honeycomb及以后的问题. (39认同)
  • @Timmmm但它实际上是我的问题,我只是将largeheap设置为true. (2认同)

Tho*_*nin 116

一般来说,在存在垃圾收集器的情况下,手动调用GC 绝不是一种好习惯.GC围绕启发式算法进行组织,这些算法在放置到自己的设备时效果最佳.手动调用GC通常会降低性能.

偶尔,在一些相对罕见的情况下,人们可能会发现某个特定的GC出错了,然后手动调用GC可能会改善性能.这是因为实际上不可能实现"完美"的GC,它将在所有情况下以最佳方式管理内存.这种情况很难预测,并取决于许多微妙的实施细节."良好实践"是让GC独立运行; 手动调用GC是一个例外,只有在实际性能问题得到适当见证后才能设想.

  • +1是一个良好的平台无关答案.在选择之前,等待有人想出一个特定于Android的答案. (8认同)
  • 我同意你写的内容*如果*你允许"性能"意味着比CPU效率更通用的东西.在Android设备上,用户对性能的看法至关重要.例如,当用户按下按钮时,开发人员可能更喜欢运行GC,因此用户将不会知道GC. (8认同)
  • 在游戏运行期间GC不运行通常很重要(这要求所有对象都是预先创建和回收的或类似的),但是当游戏暂停时,这是GC的好时机. (5认同)
  • 预蜂窝,位图数据不存储在VM存储器中.由于位图使用过多的非VM内存,系统将无法检测到并运行GC(这将运行释放非VM内存的`Bitmap.finalize()`方法).因此,在这种情况下,你*应该*遍历GC的头部并在适当的地方运行`Bitmap.recycle()`或`System.gc()`.但只有预蜂窝. (4认同)

小智 26

如果我们没有正确处理位图,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);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中刚刚尝试回收位图,这将允许你释放已用的内存空间,因此内存可能不会发生.我试过它对我有用.

如果仍然面临问题,您也可以添加这些行

BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看此链接

http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html


注:由于造成执行GC瞬间"暂停",这是建议之前做到这一点的每个位分配.

最佳设计是:

  1. 通过显示的代码释放不再需要的所有位图if / recycle / null.(制定方法来帮助解决这个问题.)

  2. System.gc();

  3. 分配新的位图.

  • 在回收位图后,不应该调用`System.gc()`吗? (4认同)

And*_*s_D 19

如果你得到一个OutOfMemoryError,那么调用垃圾收集器通常为时已晚......

以下是Android开发者的报价:

大多数情况下,垃圾收集是因为大量的小型短期对象而发生的,而一些垃圾收集器(如分代垃圾收集器)可以优化这些对象的收集,以便应用程序不会经常中断.遗憾的是,Android垃圾收集器无法执行此类优化,因此在性能关键代码路径中创建短期对象对您的应用程序来说非常昂贵.

所以据我所知,没有迫切需要打电话给gc.最好花更多的精力避免不必要的对象创建(比如在循环内创建对象)

  • 不能用另一种方式解释报价吗?可能需要手动调用GC以便在消耗过多内存之前收集这些对象. (6认同)

小智 7

我的应用程序管理了很多图像,并且它因OutOfMemoryError而死亡.这对我有帮助.在Manifest.xml中添加

<application
....
   android:largeHeap="true"> 
Run Code Online (Sandbox Code Playgroud)

  • 谷歌不喜欢这个 (9认同)
  • 除非您确定自己在做什么,否则不要使用 largeHeap。使用大堆会使垃圾收集器的工作更加困难,因为它必须在清除内存之前循环处理大量垃圾数据。 (2认同)

cmi*_*cat 7

它似乎System.gc()不适用于Art Android 6.0.1 Nexus 5x,所以我使用了Runtime.getRuntime().gc();.

  • `System.gc()` 是 `Runtime.getRuntime().gc()` 的包装函数。请参阅https://android.googlesource.com/platform/libcore/+/5aced732888f8737c9c30ddf6e2e16ee911c4a54/luni/src/main/java/java/lang/System.java#194 (2认同)

Igo*_*daš 6

一般来说,您不应该使用System.gc()明确调用GC.甚至还有IO讲座(http://www.youtube.com/watch?v=_CruQY55HOk),他们解释了GC暂停日志的意思,并且他们也声明从不调用System.gc(),因为Dalvik知道更好比你什么时候这样做.

另一方面,正如上面的答案所述,Android中的GC过程(就像其他一切一样)有时会出错.这意味着Dalvik GC算法与Hotspot或JRockit JVM不相同,并且在某些情况下可能会出错.其中一种情况是分配位图对象.这是一个棘手的问题,因为它使用Heap和Non Heap内存,并且因为内存受限设备上的一个松散的位图对象实例足以为您提供OutOfMemory异常.因此,在您不再需要此位图之后调用它通常是由许多开发人员建议的,甚至被某些人认为是好的做法.

更好的做法是在位图上使用.recycle(),就像这个方法一样,因为它将位图的本机内存标记为可以安全删除.请记住,这是非常依赖于版本的,这意味着它通常在较旧的Android版本(我认为是3.0版)上是必需的,但在以后的版本中不需要.此外,在较新版本的Ether上使用它也不会有太大的伤害(只是不要在循环或类似的东西中这样做).新的ART运行时在这里发生了很大的变化,因为它们为大对象引入了特殊的Heap"分区",但我认为使用ART ether来做这件事并不会有太大的影响.

关于System.gc()的另一个非常重要的注意事项.此方法不是Dalvik(或JVM)有义务响应的命令.考虑更像是对虚拟机说"如果不麻烦,请你做垃圾收集".