2014-01-27 4 views
3

У меня есть приложение java, через несколько часов оно выполняет память. Я пытался обнаружить утечку памяти с помощью visualvm, но он показывает неправильные данные (не знаю, как это может произойти).Явная утечка памяти, visualvm показывает неправильные данные

На скриншоте вы можете увидеть, диспетчер задач показывает использование памяти 700MB и VisualVM показывает 225 ...

Кто-нибудь знает, что происходит здесь?

С уважением

enter image description here

+1

если утечка памяти происходит набор -XX: PermSize = 256m -XX : MaxPermSize = 256m как аргументы VM – lakshman

+0

@Vach Это не похоже на утечку памяти ... – assylias

+0

@lakshman это вообще не устраняет утечку памяти PermGenSize, это просто задерживает актуальную проблему. Лучшим предложением было бы предложить структуру, которая фактически может разгружать классы, если они больше не нужны/не используются.Это, однако, требует разумной классовой загрузки и, кроме того, довольно строгой обработки (особенно одиночных и перечислений) –

ответ

4

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

Например, если вы запустите программу, как этот

java -Xmx512m -Xms256m ... 

Тогда ваша JVM будет принимать 256 МБ, как только он начинает (и ОС вам скажу так, более или менее). Однако, если вы откроете инструмент подглядывания памяти (будь то visualvm, jconsole и т. Д.), Это может показать, что вы используете меньше, чем это (вам просто не нужно использовать всю вашу зарезервированную кучу).

+0

ok «он может показать, что я использую меньше, чем это», но если я запустил данное java-приложение с использованием -Xmx512, это означает, что 512 является максимальной памятью, определенной для что приложение и диспетчер задач теоретически не должны показывать больше выделенных 512? или я чего-то не понял? – vach

+1

Это будет максимальный размер кучи, но есть и другие области, занимающие больше пространства ОС (apppace пространства, в котором JVM нуждается, чтобы поместить свой собственный код и переменные в память). Возьмите его как ориентацию (но весьма полезную для установки пределов JVM) –

3

Что Java получает, он не возвращается. Выделение памяти требует больших усилий, поэтому Java обычно не возвращает какую-либо память, которую когда-либо предоставляла система. Поэтому, если ваша программа когда-либо использовала 760 МБ ОЗУ, это то, что она придерживается.

И тогда есть две другие факторы, которые играют важную роль. Размер кучи - это только объем памяти, которую ваша программа использует или может использовать. Но между вашей программой и ОС есть Java-VM, которая также может иметь хорошую память. Диспетчер задач показывает объем памяти, который используется вашей программой, плюс vm.

Другим фактором является фрагментация памяти. Некоторые структуры данных (например, массивы) должны быть в последовательном блоке памяти. массив [i + 1] должен находиться в слоте памяти после массива [i]. Это означает, что если у вас есть, например, 10 МБ, а средняя память 2 МБ используется, и вы хотите создать массив размером 6 МБ, на котором Java-VM должна выделить новую память, поэтому она может соответствовать массиву в один кусок. Это увеличивает использование памяти в диспетчере задач вверх, но не размер кучи, так как размер кучи показывает только фактическую используемую память.

+2

на самом деле, GC заботится о проблемах «дефрагментации», как вы описали, путем переустановки памяти при очистке и освобождении неиспользуемых объектов. –

+1

Хорошо, имеет смысл. Ну, вероятно, это произойдет только тогда, когда будет проведен GC, который может не совпадать с распределением. Тем более, что нет жесткого стандарта о том, когда GC работает. – Dakkaron

2

Пространства памяти в Java определяются тремя метриками: используются, доступны, доступны максимум (см. Значения JMX). Размер, который вы видите, доступен для размера, а не максимально доступного, который, вероятно, уже выделен. Снова вы также должны показать не кучу памяти (обычно меньше, чем кучу, но вы должны настроить ее по-другому) Чтобы быть более точным, вы должны опубликовать свои настройки запуска JVM.

PS: глядя на свой профиль памяти я не вижу никакой утечки: Я могу видеть JVM сокращается размер кучи, потому что она не используется на всех

+0

Ну, если вы посмотрите на visalvm, вы не видите утечки, как насчет диспетчера задач? – vach

+0

В диспетчере задач вы можете видеть выделенную память по процессу. JVM запрашивает операционную память для своей активности на основе эвристики java и jvm, даже если в памяти нет объекта. Запрос новой памяти на ОС стоит дорого, и JVM избегает его, если это возможно. Опубликуйте настройки JVM для окончательного решения вашего вопроса. –