Есть ли гарантия, что Java OutOfMemoryError будет брошен - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть приложение Java Spring Boot.Это действительно большое приложение со множеством сервисов, которое может выполнять множество задач.Одна из новых задач, которые я пытаюсь реализовать, - это прочитать некоторые данные из базы данных Oracle и отправить их через остальные в какое-то внешнее приложение.

Данные, которые читаются, достаточно велики (трудно сказать, насколько они большие, они содержат объекты геометрии), и нужно прочитать около 1,8 миллиона записей.

Чтобы справиться с этимЯ использую "пагинацию набора ключей" как способ чтения из БД.Это означает, что я получаю последний прочитанный идентификатор и затем получаю следующую страницу на основе этого (e_id> lastReadId).Размер страницы составляет 100 сущностей.

При последнем запуске он получил страницу «6672» (667200 сущностей были прочитаны и отправлены во внешнее приложение).Стоит отметить, что я не храню никаких ссылок на эти объекты, просто извлекаю страницу, сохраняю ее список и отправляю через остальные.При следующем запуске этот список переопределяется новой страницей и т. Д.

Ниже приведен график количества выбранных объектов за 3 часа, максимум - 1030 и минимум 145 объектов.

Fetched entities per 3h

Моя проблема в том, что приложение вылетает без ошибок.В журналах я вижу, что была выбрана последняя страница (в данном случае это была «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

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

После некоторого профилирования с использованием JProfiler я смог обнаружить, что Hibernate будет кэшировать все, что было выбрано, поскольку все было сделано в одной транзакции.Добавление EntityManager.clear () в существующий цикл while решило проблему.

Также стоит отметить, что весь процесс был значительно ускорен.

0 голосов
/ 17 сентября 2018

Вы можете настроить JVM для создания дампа кучи при получении этой ошибки.

Чтобы настроить JVM для создания дампа кучи, добавьте параметр -XX: + HeapDumpOnOutOfMemoryError к параметрам Java и перезапуститеJVM.При возникновении ошибки пространства кучи JVM создает файл размером с настроенный максимальный размер кучи.

Проверьте это для подробностей https://docs.bmc.com/docs/AtriumOrchestratorPlatform/77/troubleshooting-java-virtual-machine-memory-errors-329147248.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...