首页 > 解决方案 > 是否保证会抛出 Java OutOfMemoryError

问题描述

我有一个 Java Spring Boot 应用程序。它具有许多服务的真正大型应用程序,并且可以执行大量任务。我正在尝试实施的一项新任务是从 Oracle DB 中读取一些数据并通过 rest 将其发送到某个外部应用程序。

正在读取的数据非常大(很难说有多大,它包含几何对象),大约有 180 万条记录要读取。

为了处理这个问题,我使用“keyset pagination”作为从 DB 读取的一种方式。这意味着我获得了最后读取的 id,然后根据它获得下一页(e_id > lastReadId)。页面大小为 100 个实体。

在最后一次运行中,它到达了“6672”页(已读取 667200 个实体并将其发送到外部应用程序)。值得注意的是,我不存储对这些对象的任何引用,只是获取一个页面,将其存储为列表并通过 rest 发送。在下一次运行时,该列表将被新页面覆盖,依此类推。

这是每 3 小时获取的实体数量的图表,最多为 1030 个,最少为 145 个实体。

每 3 小时获取的实体

我的问题是应用程序崩溃而没有任何错误。在日志中,我可以看到最后一页已被获取(在本例中是“6672”,有时是其他页面),然后突然有一条日志消息在我的应用程序启动时记录下来。

我的第一个想法是它内存不足并且崩溃了。但没有迹象表明这一点。是否保证会在此时抛出 OutOfMemoryError ?我应该看别的东西吗?也许我做错了什么。

编辑

我正在为您添加一些代码,以查看我如何执行这些操作

// Get first page, last read id is null
List<MyEntity> data = dataService.collectData(pageSize, null);

sendDataToExternalService(data);
while(true) {
    final String lastReadID = data.get(data.size() - 1).getId();
    data = dataService.collectData(pageSize, lastReadID);
    sendDataToExternalService(data);
}

方法sendDataToExternalService看起来像这样

restTemplate.exchange("some/url/to-external-app", HttpMethod.PUT, new HttpEntity<>(data), List.class);

RestTemplate 是org.springframework.web.client.RestTemplate

标签: javaspringcrashout-of-memory

解决方案


您可以将 JVM 配置为在收到此错误时生成堆转储。

要配置 JVM 以生成堆转储,请将 -XX:+HeapDumpOnOutOfMemoryError 选项添加到 Java 选项并重新启动 JVM。当发生堆空间错误时,JVM 会创建一个大小为配置的最大堆大小的文件。

检查此以获取详细信息 https://docs.bmc.com/docs/AtriumOrchestratorPlatform/77/troubleshooting-java-virtual-machine-memory-errors-329147248.html


推荐阅读