简体   繁体   English

内存不足时,Java GC是否可以运行?

[英]Is Java GC run when I'm out of memory?

I'm developing an Android-based 3D game in Java (not using the NDK). 我正在用Java开发基于Android的3D游戏(不使用NDK)。 One of the must-haves for any game is a resource cache, in which I can store loaded textures, meshes, sounds, etc. 任何游戏的必备工具之一是资源缓存,其中可以存储加载的纹理,网格,声音等。

My plan is to develop a resource cache that hands out weak references to certain resources, so that only the cache itself keeps a strong reference to the resource, meaning that if I remove a resource from my cache, it will be garbage collected without me having to worry about it. 我的计划是开发一个资源高速缓存,该高速缓存不会发出对某些资源的弱引用,因此只有高速缓存本身会保留对资源的强引用,这意味着,如果我从高速缓存中删除资源,它将在没有我的情况下被垃圾回收。担心它。

I'm having a hard time finding an answer to the following question though: Say I have filled my resource cache to the point where my heap space is almost completely full. 但是,我很难找到以下问题的答案:假设我已将资源缓存填满到堆空间几乎完全满的程度。 I now want to load an additional resource, but its memory footprint is so large that it won't fit in my available heap space. 现在,我想加载一个额外的资源,但是它的内存占用空间太大,以致无法容纳我的可用堆空间。 To accommodate for the new object's size, I remove some entries from my cache and I load in the new object. 为了适应新对象的大小,我从缓存中删除了一些条目,然后加载了新对象。 Will this possibly cause an OutOfMemory exception? 这可能会导致OutOfMemory异常吗? As long as the garbage collector hasn't sweeped through my recently removed objects, the memory stays in use, so is the garbage collector smart enough to run a new sweep in order to accommodate the newly allocated object? 只要垃圾收集器没有清除我最近移除的对象,内存就一直处于使用状态,那么垃圾收集器是否足够聪明以运行新的清除操作以容纳新分配的对象?

The JVM will run a Full GC before throwing an OutOfMemoryError (it doesn't want to throw OOME , so it'll attempt everything possible). JVM将在抛出OutOfMemoryError之前运行Full GC (它不想抛出OOME ,因此它将尝试所有可能的事情)。 It's just that considerate. 就这么体贴。

The [Java Machine specification states(#6.3)] states this: [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.

So JVM does guarantee that it will try what it can to free up memory through GC before it throws an OutOfMemoryError. 因此,JVM确实保证它将在抛出OutOfMemoryError之前尝试通过GC释放内存。

GC is not guaranteed to run, although it usually does. 尽管通常可以保证GC不能运行。 I know I've seen OOME without GC and GC could have made a difference but it's rare. 我知道我看到没有GC的OOME和GC可能会有所作为,但这很少见。 Usually if you've dereferenced objects and they are eligible for GC, then when you need memory allocated for new objects the JVM will do its job great and you will be fine. 通常,如果您已取消引用对象并且它们符合GC的条件,那么当您需要为新对象分配内存时,JVM会做得很好,并且会很好。 Properly dereferencing objects is usually the problem if you get an OOME and you think enough memory should be available. 如果获得OOME,并且认为应该有足够的内存,则通常会适当地取消引用对象。

See this post: 看到这篇文章:

Is the garbage collector guaranteed to run before Out of Memory Error? 是否可以保证垃圾收集器在内存不足错误之前运行?

Also you can request GC, but that also does not guarantee that it will be run, and it may not be a good idea. 另外,您可以请求GC,但这并不能保证它将运行,这可能不是一个好主意。 See this post: 看到这篇文章:

Garbage collector in Android Android中的垃圾收集器

To accommodate for the new object's size, I remove some entries from my cache and I load in the new object. 为了适应新对象的大小,我从缓存中删除了一些条目,然后加载了新对象。 Will this possibly cause an OutOfMemory exception? 这可能会导致OutOfMemory异常吗? As long as the garbage collector hasn't sweeped through my recently removed objects, the memory stays in use, so is the garbage collector smart enough to run a new sweep in order to accommodate the newly allocated object? 只要垃圾收集器没有清除我最近移除的对象,内存就一直处于使用状态,那么垃圾收集器是否足够聪明以运行新的清除操作以容纳新分配的对象?

By remove I understand you set them to null to make them eligible for GC . 删除后,我了解到您将它们设置为null即可使它们符合 GC Although you have set them to null, the GC might decide not to do a memory sweep at all. 尽管将它们设置为null,但GC可能会决定根本不进行内存扫描。 Now you could explicitly call System.gc but then again the GC will be running in a separate low-priority thread. 现在,您可以显式调用System.gc但是GC将再次在单独的低优先级线程中运行。 And collection of Objects will not be immediate . 并且对象的收集将不是立即的 Now, once you try to load the large resource, the GC finds out that the memory is less, it starts its task to free as much memory as possible. 现在,一旦您尝试加载大资源,GC就会发现内存不足,它将开始执行其任务以释放尽可能多的内存。 But it will still throw OutOfMemory because you don't have memory when trying to load your resource. 但是它仍然会抛出OutOfMemory因为尝试加载资源时没有内存。

I just found out the answer to my own question in accordance with what Kayaman said earlier: 我只是根据卡亚曼先前所说的找到了自己的问题的答案:

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. Java虚拟机实现已用完虚拟内存或物理内存,并且自动存储管理器无法回收足够的内存以满足对象创建请求。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM