Назад | Перейти на главную страницу

JVM в Windows - подкачка и полные сборщики мусора

У нас есть приложение на основе Java (TeamCity, на Tomcat, на Java 1.7), работающее в Windows (Server 2012 R2). Java работает с максимальным размером кучи 6 ГБ, а система имеет 10 ГБ ОЗУ. Это единственная служба, не связанная с ОС, работающая на машине.

Для устойчивого состояния все нормально. К сожалению, когда Java иногда выполняет полный сборщик мусора, мы обнаруживаем, что часть кучи Java была выгружена, и ее необходимо вернуть, и поэтому сборщик мусора занимает несколько минут, а не менее нескольких секунд.

Общая мудрость никогда не заключается в том, чтобы полностью отключать файл подкачки Windows, но мне интересно, не является ли это контрпримером? (Мы действительно не хотим, чтобы мир останавливался на несколько минут, пока он отправляет его обратно для сборки мусора!)

Есть ли лучший способ гарантировать, что JVM никогда не будет выгружаться на диск, в свете рабочей нагрузки с большим количеством операций ввода-вывода, заставляющей Windows вытеснять часть кучи в пользу дискового кеша?

Спасибо Роб

Тьфу, Ява. :(

Сначала я дам вам короткий ответ: да, я думаю, это может быть веской причиной для запуска без файла подкачки, зная, конечно, что вы больше не сможете создавать аварийные дампы системы, и ваша машина выйдет из строя или дестабилизируйте до такой степени, что вы бы хотели, чтобы он разбился, если у вас закончится память. Однако вам просто нужно взвесить для себя все «за» и «против». Технически Windows может нормально работать без файла подкачки до тех пор, пока вы не запускаете его из памяти ... например, за исключением старых или плохо спроектированных приложений, которые по глупости предполагают существование файла подкачки.

Теперь длинный ответ.

Во-первых, почему происходит пейджинг? Операционная система использует алгоритм замены страниц, где каждая страница памяти помечается "возрастом", который является счетчиком с момента последнего обращения к этой странице памяти. Страницы памяти, к которым не обращались долгое время, в конечном итоге записываются на диск, так что другим потенциально более важным данным может быть предоставлено место в ОЗУ. Если процесс чаще активно использует выделенную память, вероятность того, что эти страницы будут записаны в файл подкачки, меньше.

Разработчики приложений могут позвонить в VirtualLock Функция Windows API, чтобы попросить Windows заблокировать страницы в рабочем наборе вызывающего процесса. Однако для успешного вызова этой функции требуется определенная привилегия операционной системы, поскольку возможность блокировки страниц в ОЗУ потенциально может иметь неблагоприятные последствия для всей системы, если вы не играете хорошо. Но это тебе не поможет, потому что VirtualLock это то, что вы могли бы использовать в своем коде при разработке приложения. Это не то, что вы можете вызвать в чьем-то запущенном процессе.

Но с Java теперь вы запускаете виртуальную машину со своим собственным менеджером внутренней памяти поверх реальной операционной системы и ее менеджера памяти, и эти два не всегда хорошо работают вместе, как вы сами. Блокировка процесса (или, точнее, блокировка всей памяти, выделенной процессом) в физической памяти зависит от операционной системы и, как таковая, не может обрабатываться Java, поскольку Java стремится быть агностиком и перекрестным. Платформа.

Итак, единственный известный мне способ заставить Java заблокировать свои выделения в ОЗУ, чтобы они не выгружались, - это использовать JNI (собственный интерфейс Java) и mlock()/mlockall().