Я тестирую использование размера кучи в приложении Java, запущенном в JDK 1.6. Я использую инструмент VisualVM для отслеживания использования кучи. Я нашел максимальное использование кучи размером около 500 МБ в течение нескольких минут. Я использовал опцию «Выполнить GC», которая вызывает System.gc(). В первый раз, когда я использовал его, максимальная куча была уменьшена до 410 МБ, затем я снова использовал ее, чтобы получить 130 МБ, а в следующий раз - до 85 МБ. Я сделал все четыре звонка рядом со следующим без каких-либо интервалов. Почему вызов System.gc() не собирает всю кучу до 85 МБ в первый раз. Есть ли еще одна причина этого. Или я должен попробовать с любыми другими методами?System.gc не очищается за один проход. Использует 3 или более вызовов для очистки
ответ
System.gc() вернется, когда все объекты будут сканироваться один раз.
Объект должен быть завершен() ПОСЛЕ того, как он был собран. Большинство объектов не реализуют этот метод, но для тех, которые это делают, они добавляются в очередь для последующей очистки. Это означает, что эти объекты еще не могут быть очищены (а не узлы очереди, которые их удерживают), то есть действие запуска GC может увеличить время на потребление памяти.
Кроме того, существуют SoftReferences для объектов, которые могут быть очищены или не очищены GC. Предполагается, что их следует очищать только в том случае, если не было очищено больше.
Короче говоря, не все объекты могут быть очищены за один цикл.
System.gc() просит JVM начать сбор мусора. Если вы ожидаете, что GC вызывается, как только System.gc(), это неправильное понятие. Вызов его несколько раз не поможет. Невозможно сопоставить System.gc() с фактической сборкой мусора. Также независимо от того, сколько раз вы вызываете System.gc(), JVM будет выполнять GC только тогда, когда это будет сделано. Что может случиться, так это то, что размер кучи уменьшается даже при первом System.gc(), но не точно, как только вы его вызываете. Сбор мусора, связанный с вашим первым System.gc(), может заканчиваться в фоновом режиме, и параллельно ваш код достигает третьего оператора System.gc().
Если вы уверены, что только добавление нескольких System.gc() поможет вам уменьшить размер кучи. Затем вам нужно проверить, что все объекты создаются в JVM между первым и последним System.gc(). Могут быть другие потоки, создающие объекты.
Одной из возможных причин может быть использование типов java.lang.ref.Reference
. Если GC собирается сломать «Ссылка», это произойдет после завершения собственно GC. Любые объекты, которые становятся недоступными в результате, оставляются для следующего цикла GC.
Завершение работ аналогичным образом. Если объект требует завершения, он и все объекты, доступные из него (только), скорее всего, будут собираться только в следующем цикле GC.
Тогда возникает проблема, что алгоритм GC для сжатия кучи является неагрессивным. Согласно странице Java HotSpot VM Options, GC только сжимает кучу, если после сбора мусора более 70% свободных. Однако не совсем ясно, относится ли это к полному GC или нет. Таким образом, вы можете заставить GC делать частичный GC и сокращаться, а затем полный GC и сокращать еще немного.
(Некоторые люди вывести из формулировки System.gc()
Javadocs, что он будет выполнять полный GC. Тем не менее, я подозреваю, что это на самом деле версия/GC зависима.)
Но, честно говоря, это должно все быть спорным. Попытка принудить приложение к возвращению столько памяти возможно бессмысленно. Скорее всего, вы вынуждаете его удалять кешированные данные.Когда приложение снова активируется, он начнет перезагрузку своих кешей.
Спасибо .. Есть ли способ заставить JVM собирать все объекты для очистки? –
Он собирает все доступные в то время объекты. Проблема в том, что некоторые объекты не могут быть собраны немедленно. Существует работа, которая должна выполняться после того, как объект был собран, и это не может быть выполнено во время GC, поэтому ответ будет; то, что вы хотите, невозможно с текущей реализацией. например финализаторы не могут работать, пока выполняется полная коллекция, а это, в свою очередь, создает мусор, который неизбежен в общем случае. –
Вообще говоря, вы должны минимизировать использование финалистов и ссылок. Если это проблема, я бы посмотрел на исправление кода, чтобы он не использовал их так сильно. –