2013-06-17 3 views
7

При просмотре моего удаленного применения в JVisualVM над JMX, я вижу пилообразное использование памяти во время простоя:выследить распределения ИНТА []

enter image description here

Принимая дамп кучи и анализ его с JVisualVM, я вижу, что большая часть памяти находится в нескольких больших массивах int[], у которых нет ссылок, и, сравнивая кучи кучи, я вижу, что они, похоже, берут память и периодически регенерируются GC.

Мне любопытно отследить их, так как это вызвало мой интерес к тому, что мой собственный код никогда не сознательно выделяет любые int[] массивы.

Я использую много библиотек, таких как netty, чтобы преступник мог быть в другом месте. У меня есть другие серверы с таким же сочетанием фреймворков, но не вижу этого там.

Как узнать, кто их распределяет?

+0

Примите во внимание, что, хотя у вас буквально нет 'new int []', вы все равно можете выделить их самостоятельно. Массив теоретически - единственное, что можно выделить в Java. –

+1

@MarkoTopolnik Да, будучи сетевым сервером, у меня есть некоторый 'byte []', вокруг которого я могу учитывать. Его большой временный 'int []', который мне интересен, хотя я понимаю, что они будут исправлены, как только появится GC; они могут вызывать GC более часто, чем хотелось бы, но, похоже, они, похоже, не влияют на сервер. Мне просто интересно, как вы собираетесь отлаживать его. – Will

+2

[Эта ссылка] (http://stackoverflow.com/a/12017652/1103872) должна помочь. –

ответ

2

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

Это не ответ на ваш вопрос, но мой вопрос:

Почему вы заботитесь?

Вы сказали, что сборщик мусора jvm (GC) может использовать до 1 ГБ памяти. Java использует менее 250M.

GC пытается быть умным, когда собирает мусор, а также, как сильно он работает при сборке мусора. На вашем графике нет потребности в памяти. Jvm не находится рядом с установленным пределом 1 ГБ. Я не вижу причин, по которым GC должен очень стараться. Не уверен, почему вам тоже будет интересно.

Его хорошая вещь для сборщика мусора, чтобы быть ленивым. Чем меньше работает GC, тем больше ресурсов доступно для вашего приложения.

Вы пробовали запускать GC через кнопку JVisualVM «Выполнить GC»? Эта кнопка должна инициировать операцию по сборке мусора «остановить мир». Попробуйте, когда график находится посередине одного из этих скачков зубьев пилы - я предсказываю, что использование упадет на основание пилы или ниже. Если это так, это доказывает, что зуб за память - это просто накопление мусора, и GC делает все правильно.

Вот скриншот использования памяти для приложения Java Swing, я использую: enter image description here

Уведомления пилообразного узора.

Вы сказали, что беспокоитесь о int []. Когда я начинаю профайлер памяти и иметь его профиль все, что я могу видеть распределения ИНТ []

enter image description here

В основном все распределения приходят от метода ObjectOutputStream $ HandleTable.growEntries. Похоже, что поток, на который были сделаны выделения, был развернут для обработки сетевого сообщения.
Я подозреваю, что это вызвано самой jmx. Возможно, rmi (вы используете rmi?). Или отладчик (у вас есть отладчик подключен?).

+0

Thx для задумчивого ответа, Райан. Когда я сказал, что у них нет ссылок, я имел в виду, что я не вижу, кто их держит - никто. Это мусор. Мне еще не удалось сделать снимок, пока кто-то еще его удерживает. Итак, вопрос в том, кто их создает и почему? И как бы вы отследили его? С уважением, вопрос большой, я профилирование кучи моего приложения, потому что под нагрузкой он использует гораздо больше памяти, чем мне нравится, и я сталкиваюсь со всеми видами отчетов о нехватке памяти у пользователей в этой области. Так что видеть это пилообразное, в то время как свободное время интересно отслеживать. – Will

+0

Кроме того, ваши трассировки стека очень интересны, и его аккуратный вы можете увидеть поток объектов там. У меня нет профилировщика памяти, потому что все мои серверы, даже тестовые, являются «удаленными», и это ограничение jvisualvm. – Will

+0

@Will - вам действительно нужно проанализировать кучу приложения, когда у него заканчивается память - вы не будете очень далеко смотреть на приложение, когда оно не находится под нагрузкой. -XX: + HeapDumpOnOutOfMemoryError чрезвычайно полезен. Автономный анализатор памяти Eclipse также является отличным бесплатным инструментом. – Ryan

1

Я просто подумал, что добавлю к этому вопросу, что пилообразный паттерн очень нормальный и не имеет ничего общего с вашими int[] массивами. Это происходит потому, что в Eden-gen происходят новые распределения, и только эфемерная коллекция запускается только после того, как она заполнилась, оставив старый ген. Поэтому, пока ваша программа вообще выполняет какие-либо ассигнования, генерал Eden будет заполняться, а затем повторно пустым. Тем более, если у вас есть регулярное количество ассигнований за единицу времени, вы увидите очень обычный пилообразный рисунок.

Есть тонны статей в Интернете, в которых подробно описывается, как работает GC Hotspot, поэтому мне не нужно расширять его здесь. Если вы вообще не знаете, как работает эфемерная коллекция, вы можете проверить Wikipedia's article on the subject (см. Раздел «Generational GC», «generational» и «ephemeral» являются синонимами в этом контексте).

Что же касается массивов int[], они немного загадочны. Я тоже вижу их, и есть another question here on SO на тему их без реального ответа. На самом деле это не нормально для объектов, не имеющих ссылок на отображение в дампе кучи, потому что куча кучи обычно содержит только живые объекты (поскольку Hotspot всегда выполняет стоп-мировую коллекцию до фактического сброса кучи). Моя личная догадка заключается в том, что они выделяются как часть некоторой внутренней структуры данных JVM (и поэтому имеют только ссылки из C++-части Hotspot, а не из кучи Java), но это действительно просто предположение.