Eclipse возвращает кучу обратно в систему

Я использую Eclipse 3.6 с последней версией Sun Java 6 в Linux (64-разрядная версия) с большим количеством крупных проектов. В некоторых особых случаях (например, обновления SVN) Eclipse требуется до 1 ГБ кучи. Но в большинстве случаев требуется всего 350 МБ. Когда я включаю панель состояния кучи, я вижу это большую часть времени:

350M of 878M

Я запускаю Eclipse с такими настройками: -Xms128m -Xmx1024m

Таким образом, большую часть времени многие МБ просто тратятся впустую и используются редко, когда использование памяти достигает пика в течение короткого времени. Мне это совсем не нравится, и я хочу, чтобы Eclipse освободил память обратно в систему, чтобы я мог использовать ее для других программ.

Когда Eclipse требуется больше памяти, а свободной оперативной памяти недостаточно, чтобы Linux мог подкачать другие запущенные программы, я могу с этим смириться. Я слышал, что есть опция -XX:MaxHeapFreeRatio. Но я никогда не понимал, какие значения я должен использовать, чтобы это работало. Ни одно значение, которое я пробовал, никогда не имело значения.

Итак, как я могу сказать Eclipse (или Java) освободить неиспользуемую кучу?


person kayahr    schedule 23.09.2010    source источник
comment
Вы пробовали этот eclipse.ini (stackoverflow.com/questions/142357/) с вашими настройками Xms Xmx?   -  person VonC    schedule 23.09.2010


Ответы (3)


Нашел решение. Я переключил Java на использование сборщика мусора G1, и теперь параметры HeapFreeRatio работают как положено. Поэтому я использую эти параметры в eclipse.ini:

-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC
-XX:MinHeapFreeRatio=5
-XX:MaxHeapFreeRatio=25

Теперь, когда Eclipse съедает более 1 ГБ ОЗУ для сложной операции и переключается обратно на 300 МБ после сборки мусора, память фактически освобождается обратно операционной системе.

person kayahr    schedule 14.02.2011

Вы можете пойти в Preferences -> General и проверить Show heap status. Это активирует хороший вид на вашу кучу в углу Eclipse. Что-то вроде этого:

альтернативный текст

Если вы нажмете на корзину, она попытается запустить сборку мусора и вернуть память.

person nanda    schedule 23.09.2010
comment
Я знаю этот дисплей состояния (даже упомянул об этом в своем вопросе), и я знаю эту кнопку корзины, но она только запускает сборщик мусора и НЕ возвращает никакой памяти в систему. Таким образом, если у Eclipse был короткий пик использования памяти в 1 ГБ, размер кучи навсегда останется равным 1 ГБ (пока я не перезапущу Eclipse), даже если фактически используется только 300 МБ кучи. - person kayahr; 23.09.2010

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

JVM находится во власти реализаций хост-системы malloc(), которая выделяет память из системы, используя brk(). В системах Linux (и в Solaris тоже) память, выделенная для кучи процесса, почти никогда не возвращается, в основном потому, что она становится фрагментированной, а куча должна быть непрерывной. Это означает, что память, выделенная процессу, будет монотонно увеличиваться, и единственный способ уменьшить ее размер — вообще не выделять ее.

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


Разработка из комментария ниже:

Стандартный способ для программы, написанной на C (в частности, для JVM, работающей с Eclipse), для выделения памяти — это вызвать malloc(3), который использует предоставленный ОС механизм для выделения памяти процессу, а затем управляет отдельными выделениями в рамках этих выделений. Детали того, как работают malloc() и free(), зависят от реализации.

В большинстве разновидностей Unix процесс получает ровно один сегмент данных, представляющий собой непрерывную область памяти с указателями на начало и конец. Процесс может настроить размер этого сегмента, вызвав brk(2) и увеличив конечный указатель, чтобы выделить больше памяти, или уменьшив его, чтобы вернуть его системе. Только конец можно отрегулировать. Это означает, что если ваша реализация malloc() увеличивает сегмент данных, соответствующая реализация free() не может его уменьшить, если только не определит, что в конце есть свободное место, которое не используется. На практике огромный кусок памяти, выделенный с помощью malloc(), редко оказывается в самом конце сегмента данных, когда вы его free(), вот почему процессы имеют тенденцию к монотонному росту.

person Blrfl    schedule 23.09.2010
comment
Означает ли это, что это проблема операционной системы и память правильно возвращается в систему в Windows? Есть ли официальные источники заявления о том, что это не работает в Linux? - person kayahr; 23.09.2010
comment
Это не проблема ОС. В вашем случае это комбинация того, сколько памяти процесса ваша JVM выделяет для кучи Java, как она освобождается и как память процесса обрабатывается распределителем, используемым JVM (обычно libc malloc()). Я немного подробнее остановился на этом в своем первоначальном ответе. Любое официальное заявление о том, как ведет себя конкретная реализация, будет источником для этой реализации. - person Blrfl; 23.09.2010