Java OutOfMemoryError из-за того, что кэш-память ОЗУ Linux не освобождена - PullRequest
1 голос
/ 21 мая 2010

Процесс будет работать нормально весь день, тогда, Бэм, без предупреждения, он выдаст эту ошибку. Иногда, казалось бы, в середине ничего не делать. Это будет происходить в, казалось бы, случайное время в течение дня. Я проверил, работает ли что-нибудь еще на машине, как запланированные резервные копии или что-то, но ничего не нашел. У машины достаточно физической памяти (2 ГБ, около 1 ГБ свободно для загрузки 3-500 МБ) и достаточно заданного значения -Xmx.

Согласно нашему системному администратору, проблема в том, что оперативная память, которую ядро ​​использует в качестве дискового кэша (очевидно, все, кроме 8 МБ), не освобождается, когда JVM необходимо выделить память, поэтому процесс JVM выдает ошибку OutOfMemoryError. Это может быть связано с тем, что Java запрашивает ядро, достаточно ли памяти перед распределением, и обнаруживает, что этого недостаточно, что приводит к сбою.

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

Кто-нибудь еще сталкивался с проблемой, и если да, то в чем была ошибка, и как вы ее решили? В настоящее время мы используем jdk1.6.0_20 в SLES 10 SP2 Linux 2.6.16.60-0.42.9-smp в VMWare ESX.

Ответы [ 2 ]

2 голосов
/ 21 мая 2010

По словам нашего системного администратора, проблема в том, что оперативная память, которую ядро ​​использует в качестве дискового кэша (очевидно, все, кроме 8 МБ), не освобождается, когда JVM необходимо выделить память, поэтому процесс JVM выдает ошибку OutOfMemoryError.

Я думаю, что ваш сисадмин понял это неправильно. Linux будет автоматически и прозрачно расти и уменьшать размер буферного кеша в зависимости от потребности системы в физической памяти для запуска процессов. Если этого не произойдет, значит, в вашей ОС что-то серьезно сломано.

Более вероятно, что у вашего Java-приложения есть утечка памяти, которая заставляет его использовать постоянно увеличивающийся объем кучи. В конце концов вы бежите за предел -Xmx и получаете OOME. Я бы начал исследовать это, запустив приложение с включенным ведением журнала GC. Это скажет вам, как куча растет с течением времени, сколько места восстанавливает GC и так далее.

Другая возможность заключается в том, что у вас недостаточно настроенного пространства подкачки.

1 голос
/ 21 мая 2010

Знаете ли вы, сколько памяти Java выделило при создании этого исключения? Проблема может заключаться в том, что Java использовала всю память, указанную с -Xmx. (Помните, что -Mmx дает максимально допустимое использование памяти, поэтому java выдаст исключение OutOfMemmoryException, если его использование превысит указанный размер, даже если ядро ​​linux смогло бы дать ему больше памяти).

Но чтобы выяснить, так ли это, попробуйте дать ему значение -Xms, равное размеру, указанному в -Xms. (-Ms устанавливает начальный размер, и java должен быть ниже, поэтому он будет выделять всю необходимую память при запуске).

Если java все еще запускается и все еще дает вам исключение OutOfMemoryException, то, скорее всего, проблема в том, что ваш -Mx слишком мал.

ps: Я почти уверен, что при нормальном ядре Linux не может произойти сбой выделения памяти из-за чрезмерной загрузки ядром, поэтому, если у вас действительно не хватает памяти для всей системы, вы получите сбои страниц (и oom killer, убил бы задачу) не Java исключения. Но Java может использовать некоторые специальные функции для выделения памяти, поэтому я не уверен, применимо ли это здесь.

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