我正在Java开发一个基于Android的3D游戏(不使用NDK)。任何游戏都必须有一个资源缓存,我可以在其中存储加载的纹理、网格、声音等。
我的计划是开发一个资源缓存,分发对某些资源的弱引用,这样只有缓存本身保持对资源的强引用,这意味着如果我从缓存中删除一个资源,它将被垃圾收集,而不必担心它。
不过,我很难找到以下问题的答案:假设我已经填满了我的资源缓存,以至于我的堆空间几乎完全满了。我现在想加载一个额外的资源,但是它的内存占用如此之大,以至于它不适合我的可用堆空间。为了适应新对象的大小,我从缓存中删除了一些条目,并加载了新对象。这可能会导致OutOfMemory异常吗?只要垃圾收集器没有清理我最近删除的对象,内存就会继续使用,那么垃圾收集器是否足够聪明,可以运行新的清理以适应新分配的对象?
JVM将在抛出OutOfMemoryError
之前运行一个全GC
(它不想抛出OOME
,所以它会尝试一切可能的方法)。它就是那么体贴。
GC不能保证运行,尽管它通常会运行。我知道我见过没有GC的OOME,GC可能会有所不同,但这很少见。通常,如果你取消了对象的引用,并且它们有资格GC,那么当你需要为新对象分配内存时,JVM会很好地完成它的工作,你会没事的。如果你得到一个OOME,并且你认为应该有足够的内存,正确取消对象引用通常是个问题。
看到这篇文章:
垃圾收集器是否保证在内存不足错误之前运行?
您也可以请求GC,但这也不能保证它会被运行,这可能不是一个好主意。请参阅这篇文章:
Android中的垃圾收集器
[Java机器规范声明(#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释放内存。