2016-08-27 1 views
1

У меня есть приложение Java 8, которое принимает сообщения по сети и записывает в несколько файлов с памятью, используя Java NIO MappedByteBuffer. У меня есть читатель, который читает сообщения одновременно из этих файлов по порядку и снова удаляет файлы чтения с помощью MappedByteBuffer. Все гладко, пока я не написал и прочитал о 246 Гб данных и моих сбоев приложения со следующимиПриложение Java 8 с использованием всей системной памяти, а затем сбой с помощью SIGBUS. Что тут происходит?

[thread 139611281577728 also had an error][thread 139611278419712 also had an error][thread 139611282630400 also had an error][thread 139611277367040 also had an error][thread 139611283683072 also had an error][thread 139611279472384 also had an error] 





[thread 139611280525056 also had an error] 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGBUS (0x7) at pc=0x00007f02d10526de, pid=44460, tid=0x00007ef9c9088700 
# 
# JRE version: Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13) 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode linux-amd64) 
# Problematic frame: 
# v ~StubRoutines::jint_disjoint_arraycopy 
# 
# Core dump written. Default location: /home/user/core or core.44460 
# 
# An error report file with more information is saved as: 
# /home/user/hs_err_pid44460.log 

hs_err_pid44460.log пуст и основной дамп core.44460 составляет около 246 ГБ и полна сообщений Я: пытаясь написать.

Я бегу с максимальной площадью кучи 32 ГБ. По состоянию на JConsole у меня заканчивается Free Physical Memory, а затем сбой. JConsole Screen Capture

Почему у меня заканчивается оперативная память? Я забываю закрыть некоторые дескрипторы файлов/не закрывать мои файлы с MMapped правильно?

ответ

1

Несмотря на то, что ваша программа действительно может быть правильной в использовании MappedByteBuffers, обратите внимание, что при высоком уровне размещения вы можете понести явления из-за несвоевременного освобождения упомянутых буферов, что в конечном счете является обязанностью JVM и должно происходить только во время сбор мусора буферов. Короче говоря, освобождение буфера в конечном итоге будет успешным, но , когда это произойдет, должно быть трудно предсказуемым.

Вы можете, однако, принудительно освободить («очистить») память, выделенную буферами, используя функциональность JVM Cleaner (класс sun.misc.Cleaner). Пожалуйста, обратитесь к this SO question по некоторым направлениям, но, коротко говоря, вам просто нужно позвонить по телефону Cleaner.clean() на свои буфери с выбросом как можно раньше, чтобы уменьшить цифры распределения памяти и эффективно использовать ваш прецедент.

+1

Решение состояло в том, чтобы использовать «Cleaner» для выполнения этой работы. В частности, это помогло -> http://stackoverflow.com/a/19447758/1041963 –

+2

отметить, что неправильное использование очистителя может привести к сбоям и является внутренним API, который может измениться с версии на версию – the8472

+1

@ the8472, вы правы, особенно для изменения API. Я попытаюсь обновить свой ответ как можно скорее с некоторыми указаниями для Java9, который начинает выяснять вопрос о «внутреннем» (но широко используемом!) API, см. Также: http://openjdk.java.net/jeps/260 – logtwo

0

Вам нужно будет взглянуть на область видимости виртуальной памяти или карту памяти процесса, чтобы выяснить, могут ли быть прямыми буферами.

Если это действительно сбой из-за сопоставленных или прямых буферов, то вы либо просачиваете их (работа с кучей кучи через анализатор памяти может их идентифицировать), либо GC работает слишком редко, чтобы освободить их.

+0

Запуск GC действительно помогает. Хотя G1 GC не запускает коллекцию «G1 Old Generation» достаточно часто (что, похоже, помогает). –

+0

в этом случае конфигурация GC для запуска более часто может помочь – the8472

0

Вы также можете найти более агрессивную сборку мусора.

Также хотел бы попробовать этот вариант, который был введен в J7: -XX: + UseG1GC -XX: ParallelGCThreads = 4 Это позволит в течение 4 потоков GC параллельно

Есть целый ряд хорошо статьи о дополнительной настройке вашего сборщика мусора heres one я нашел полезным (https://blogs.oracle.com/java-platform-group/entry/g1_from_garbage_collector_to)

Надеюсь, это поможет.

Смежные вопросы