1

我有一个使用 java 线程池在后台执行一些繁重处理的应用程序。

线程池配置为记录执行期间发生的异常

public enum ExceptionLogger implements Thread.UncaughtExceptionHandler {
    INSTANCE;

    private static final Logger log = LoggerFactory.getLogger(ExceptionLogger.class);

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        log.error("Exception occurred at thread " + t.getName() + "\n", e);
    }
  }

在我的应用程序日志中,我随机获取,java.lang.OutOfMemoryError: Java heap space但如果我使用记录内存使用情况,Runtime.getRuntime().freeMemory()我可以看到大量可用的可用堆空间。

此外,在我收到此异常后,应用程序继续工作。

OutOfMemoryError收到此消息还有其他原因吗?

4

2 回答 2

3

当内存分配失败时,您将收到 OutOfMemoryError。

这可能发生在

  • 你的内存用完了。
  • 您的 GC 车削参数阻止它使用所有内存。例如,为未满的代设置最小尺寸。
  • 你分配了一大块内存。在此失败后,您仍然有空闲内存,只是不足以分配大块。
  • 你会得到一个不适用于堆的 OutOfMemoryError,例如 PermGen 或直接内存或虚拟内存(用于线程等)
于 2012-11-07T13:03:12.550 回答
1

除了 Peter Lawrey 的出色回答之外,您还遇到了“达到 GC 开销限制”错误。

当 JVM 没有足够的处理时间来进行垃圾收集或 GC 占用了过多的总可用处理能力时,就会发生这种情况。主要发生在您有大量非常短暂的对象以及 CPU 饥饿的应用程序并且没有足够的平均可用堆(最大堆大小 - 长期对象)时。

对此的解决方案各不相同,但通常意味着您必须限制 CPU 消耗(在您的情况下是线程数)和/或增加堆大小。

于 2012-11-07T13:51:25.673 回答