垃圾收集器是否保证在Out of Memory Error之前运行?

如果堆已满,JVM将抛出OutOfMemoryError 。 但是它确保在抛出这样的exception之前总是发生(完全)垃圾收集吗?

这意味着当抛出exception时,内存只有强引用对象(或GC Roots可达)才能满。

编辑:假设Sun JVM – HotSpot正在讨论中。

Java机器规范在第6.3节 (强调我的)中说明:

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

因此,JVM确实保证它会在抛出OOME之前尝试通过垃圾收集释放内存。

车库收集器通常在抛出OutOfMemoryError之前运行。 但是,如果你没有GC,你可能会得到一个OOME

  • 尝试创建一个非常大的对象(例如大于堆)
  • 启动一个线程,没有足够的虚拟内存或资源来启动线程。
  • 如果达到最大直接内存,旧版本的Java会抛出此错误。

您无法保证已执行完整的垃圾收集,但VM已尝试通过垃圾收集提供足够的内存。 您可以在OutOfMemoryError类的API文档中找到:

当Java虚拟机由于内存不足而无法分配对象时抛出,垃圾收集器不再提供更多内存。

请注意,在某些情况下,垃圾收集器可以在没有实际尝试丢弃未引用的对象实例的情况下确定没有足够的内存。 最明显的例子是,如果您尝试一次性分配更多内存(例如,大字节数组),而不是最大堆大小。 在这种情况下,可能会抛出OutOfMemoryError而根本不运行垃圾收集器。

无法保证OutOfMemoryError之前的最后一个操作是垃圾回收。 最有可能的不是,因为垃圾收集会减少使用的内存量而不会增加它。

除了人们已经回答的内容之外,还有其他因素需要考虑,例如您正在使用的垃圾收集策略。 考虑吞吐量垃圾收集,如果花费太多时间来收集并且没有释放足够的内存(尽管最近的更改可能已经改变了事情),这将抛出内存不足exception。 说完所有这些后我就不会假设垃圾收集发生在我正在编写的应用程序的执行过程中的任何时候……