当我内存不足时,Java GC会运行吗?

时间:2014-08-11 11:20:20

标签: java android garbage-collection

我正在用Java开发基于Android的3D游戏(不使用NDK)。 任何游戏的必备品之一是资源缓存,我可以在其中存储加载的纹理,网格,声音等。

我的计划是开发一个资源缓存,分发对某些资源的弱引用,这样只有缓存本身才能保留对资源的强引用,这意味着如果我从缓存中删除资源,它将被垃圾收集没有我担心它。

我很难找到以下问题的答案: 假设我已经将资源缓存填充到我的堆空间几乎完全填满的位置。我现在想要加载一个额外的资源,但它的内存占用量太大,以至于它不适合我的可用堆空间。 为了适应新对象的大小,我从缓存中删除了一些条目,然后加载新对象。这可能会导致OutOfMemory异常吗? 只要垃圾收集器没有通过我最近删除的对象,内存就会继续使用,垃圾收集器是否足够聪明,可以运行新的扫描以容纳新分配的对象?

5 个答案:

答案 0 :(得分:2)

JVM会在抛出Full GC之前运行OutOfMemoryError(它不想抛出OOME,所以它会尽一切可能尝试)。这只是体贴的。

答案 1 :(得分:1)

[Java Machine specification states(#6.3)]说明了这一点:

OutOfMemoryError: The Java Virtual Machine implementation has run out of either virtual
or physical memory, and the **automatic storage manager was unable to reclaim enough memory**
to satisfy an object creation request.

因此,JVM确保它会在抛出OutOfMemoryError之前尝试通过GC释放内存。

答案 2 :(得分:1)

GC并不保证能够运行,尽管它通常会运行。我知道我已经看过OOME没有GC和GC可能会有所作为,但这种情况很少见。通常,如果您已取消引用对象并且它们符合GC的条件,那么当您需要为新对象分配内存时,JVM将完成其工作,您将没事。如果你得到一个OOME并且你认为应该有足够的内存,那么正确解除引用对象通常是个问题。

见这篇文章:

Is the garbage collector guaranteed to run before Out of Memory Error?

您也可以请求GC,但这也不能保证它会被运行,这可能不是一个好主意。看这篇文章:

Garbage collector in Android

答案 3 :(得分:0)

为了适应新对象的大小,我从缓存中删除了一些条目,然后加载新对象。这可能会导致OutOfMemory异常吗?只要垃圾收集器没有通过我最近删除的对象,内存就会继续使用,垃圾收集器是否足够聪明,可以运行新的扫描以容纳新分配的对象?

通过删除,我了解您将它们设置为 null ,以使它们符合条件 GC。虽然您已将它们设置为null,但GC可能决定不进行内存扫描。现在您可以显式调用System.gc,但GC将再次在单独的低优先级线程中运行。对象集合不会立即。现在,一旦您尝试加载大型资源,GC就会发现内存较少,它会开始执行尽可能多的内存任务。但它仍会抛出OutOfMemory,因为在尝试加载资源时没有内存。

答案 4 :(得分:0)

我刚刚根据Kayaman先前所说的问题找到了我自己问题的答案:

  

Java虚拟机实现已用完虚拟或物理内存,并且自动存储管理器无法回收足够的内存来满足对象创建请求。

找到http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.3