it-swarm-ru.tech

Когда System.gc () что-то делает?

Я знаю, что сборка мусора автоматизирована в Java. Но я понял, что если вы вызываете System.gc() в своем коде, JVM может или не может решить выполнить сборку мусора в этот момент. Как это работает точно? На каком основании/параметрах именно JVM решает сделать (или не делать) GC, когда видит System.gc()?

Есть ли примеры, в которых случае стоит добавить это в свой код?

109
harry

На практике он обычно решает сделать сборку мусора. Ответ зависит от множества факторов, например, от того, на какой JVM вы работаете, в каком режиме он работает и какой алгоритм сборки мусора он использует.

Я не буду зависеть от этого в вашем коде. Если JVM собирается сгенерировать OutOfMemoryError, вызов System.gc () не остановит его, потому что сборщик мусора попытается освободить столько, сколько сможет, прежде чем он достигнет этого предела. Единственный раз, когда я видел его на практике, это в IDE, где он прикреплен к кнопке, которую пользователь может нажать, но даже там это не очень полезно.

57
jodonnell

Единственный пример, который я могу вспомнить, где имеет смысл вызывать System.gc (), - это профилирование приложения для поиска возможных утечек памяти. Я полагаю, что профилировщики вызывают этот метод непосредственно перед тем, как сделать снимок памяти.

28
Guillermo Vasconcelos

Вы не можете управлять GC в Java - решает VM. Я никогда не сталкивался со случаем, когда требуется System.gc(). Поскольку вызов System.gc() просто ПРЕДЛАГАЕТ, что VM выполняет сборку мусора, а также выполняет ПОЛНУЮ сборку мусора (старое и новое поколения в куче из нескольких поколений), то это может фактически вызвать БОЛЬШЕ циклов процессора потребляется, чем необходимо.

В некоторых случаях может иметь смысл предложить VM выполнить полную коллекцию СЕЙЧАС, поскольку вы можете знать, что приложение будет простаивать в течение следующих нескольких минут, прежде чем произойдет тяжелая работа. Например, сразу после инициализации большого количества временных объектов во время запуска приложения (то есть, я только что кэшировал ТОННУ информации и знаю, что не буду много работать в течение минуты или около того). Подумайте о IDE, таком как запуск Eclipse - он многое делает для инициализации, поэтому, возможно, сразу после инициализации имеет смысл сделать полный gc на этом этапе.

23
DustinB

Спецификация языка Java не гарантирует, что JVM запустит GC при вызове System.gc(). Это причина того, что "может или не может решить сделать GC в этот момент".

Теперь, если вы посмотрите на исходный код OpenJDK , который является основой Oracle JVM, вы увидите, что вызов System.gc() действительно запускает цикл GC. Если вы используете другую JVM, такую ​​как J9, вы должны проверить их документацию, чтобы узнать ответ. Например, JVM Azul имеет сборщик мусора, который работает непрерывно, поэтому вызов System.gc() ничего не даст

В некоторых других ответах упоминается запуск GC в JConsole или VisualVM. По сути, эти инструменты делают удаленный вызов System.gc().

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

Однако есть несколько случаев, когда вызов System.gc() может быть понятен. Рассмотрим, например, микробенчмарки. Никто не хочет, чтобы цикл ГХ происходил в середине микробенчмарка. Таким образом, вы можете запустить цикл GC между каждым измерением, чтобы убедиться, что каждое измерение начинается с пустой кучи.

22
Pierre Laporte

Вы должны быть очень осторожны, если вы звоните System.gc(). Вызов этого может добавить ненужные проблемы с производительностью в ваше приложение, и это не гарантирует на самом деле выполнить коллекцию. На самом деле можно отключить явную функцию System.gc() через аргумент Java -XX:+DisableExplicitGC.

Я настоятельно рекомендую прочитать документы, доступные по адресу Java HotSpot Garbage Collection , чтобы получить более подробную информацию о сборке мусора.

17
David Schlosnagle

System.gc() реализуется виртуальной машиной, и то, что она делает, зависит от конкретной реализации. Например, разработчик может просто вернуться и ничего не делать.

Что касается того, когда выдавать сбор вручную, то единственное время, когда вы можете захотеть это сделать, - это когда вы оставляете большую коллекцию, содержащую множество небольших коллекций - например, Map<String,<LinkedList>> - и хотите попробовать выполнить перфект и там, но по большей части, вы не должны беспокоиться об этом. GC знает лучше, чем вы - к сожалению - большую часть времени.

10
Patrick

Если вы используете прямые буферы памяти, JVM не запускает GC для вас, даже если у вас недостаточно прямой памяти.

Если вы вызываете ByteBuffer.allocateDirect() и получаете OutOfMemoryError, вы можете обнаружить, что этот вызов в порядке после запуска GC вручную.

8
Peter Lawrey

Большинство JVM запускают GC (в зависимости от параметров -XX: DiableExplicitGC и -XX: + ExplicitGCInvokesConcurrent). Но спецификация просто не так хорошо определена, чтобы впоследствии обеспечить лучшую реализацию.

Спецификация требует уточнения: Ошибка № 6668279: (спецификация) System.gc () должна указывать, что мы не рекомендуем использовать и не гарантируем поведение

Внутренне метод gc используется RMI и NIO, и они требуют синхронного выполнения, которое: это в настоящее время обсуждается:

Ошибка # 5025281: разрешить System.gc () запускать одновременные (не останавливающие мир) полные коллекции

4
eckes

Garbage Collection хорош в Java, если мы выполняем Программное обеспечение, закодированное в Java на рабочем столе/ноутбуке/сервере. Вы можете вызвать System.gc() или Runtime.getRuntime().gc() в Java.

Просто отметьте, что ни один из этих звонков не гарантирует ничего. Это всего лишь предложение для JVM запустить сборщик мусора. Это зависит от JVM, независимо от того, запускает ли он GC или нет. Итак, короткий ответ: мы не знаем, когда это произойдет. Более длинный ответ: JVM запустит gc, если у него будет время для этого.

Полагаю, то же самое относится и к Android. Однако это может замедлить работу вашей системы.

2
Naveen

Обычно VM автоматически выполняет сборку мусора, прежде чем выдать исключение OutOfMemoryException, поэтому добавление явного вызова не должно помочь, за исключением того, что оно, возможно, перемещает попадание производительности в более ранний момент времени.

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

Когда вы отображаете файл в память, я считаю, что вызов map () создает исключение IOException, когда достаточно большой блок памяти недоступен. Я думаю, что сбор мусора непосредственно перед файлом map () может помочь предотвратить это. Как вы думаете?

2
Vashek

мы никогда не сможем форсировать сборку мусора. System.gc предлагает только vm для сборки мусора, однако, на самом деле, в какое время работает механизм, никто не знает, как указано в спецификациях JSR.

2
lwpro2

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

В настоящее время я работаю над проектом, включающим среду с ограниченным объемом памяти и относительно большие объемы данных - есть несколько больших фрагментов данных, которые доводят мою среду до предела, и хотя я смог сократить использование памяти, так что теоретически все должно работать нормально, я все равно получаю ошибки пространства кучи - подробные параметры GC показывают, что он пытается собрать мусор, но безрезультатно. В отладчике я мог бы выполнить System.gc () и убедиться, что будет "много" доступной памяти ... не много дополнительной, но достаточно.

Следовательно, единственный раз, когда мое приложение вызывает System.gc (), это когда он собирается ввести сегмент кода, где будут выделены большие буферы, необходимые для обработки данных, и тест на доступную свободную память показывает, что я не гарантированно иметь его. В частности, я смотрю на среду объемом 1 ГБ, где статические данные занимают не менее 300 МБ, причем основная часть нестатических данных связана с выполнением, за исключением случаев, когда обрабатываемые данные имеют размер не менее 100-200 МБ. источник. Все это является частью процесса автоматического преобразования данных, поэтому все данные существуют в течение относительно коротких периодов времени в долгосрочной перспективе.

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

Несмотря на это, несмотря на то, что я использую System.gc (), я все еще продолжал настраиваться с использованием параметров командной строки и сумел значительно увеличить общее время обработки моего приложения, несмотря на то, что не смог преодолеть камень преткновения, возникающий при работе с большими блоками данных. При этом System.gc () - это инструмент .... очень ненадежный инструмент, и если вы не будете осторожны с его использованием, вам захочется, чтобы он работал не чаще, чем нет.

2
Kyune

Короче:

Параметры зависят от VM.

Пример использования - не могу вспомнить ни одного для приложений времени выполнения/производственных приложений, но полезно запустить его для некоторых профилирующих процессов, таких как вызов

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();
1
mataal

Если вы хотите знать, вызывается ли ваша System.gc(), вы можете с помощью нового Java 7 update 4 получать уведомление, когда JVM выполняет сборку мусора.

Я не уверен на 100%, что класс GarbageCollectorMXBean был представлен в Java 7 обновление 4, потому что я не смог найти его в примечаниях к выпуску, но нашел информацию в сайт javaperformancetuning .com

1
Shervin Asgari

Согласно "Размышлению в Java" Брюса Эккеля, один из вариантов использования явного вызова System.gc () - это когда вы хотите принудительно завершить, т.е. вызов метода финализировать.

0
Asterisk

Я не могу вспомнить конкретный пример, когда хорошо запустить явный GC.

В общем, запуск явного GC может на самом деле принести больше вреда, чем пользы, потому что явный gc вызовет полную коллекцию, которая проходит значительно дольше, когда проходит через каждый объект. Если этот явный gc будет вызываться повторно, это может легко привести к медленной работе приложения, так как много времени тратится на выполнение полных GC.

В качестве альтернативы, если вы просматриваете кучу с помощью анализатора кучи и подозреваете, что компонент библиотеки вызывает явные GC, вы можете отключить его, добавив: gc = -XX: + DisableExplicitGC к параметрам JVM.

0
zxcv

пока работает system.gc, он остановит мир: все ответы останавливаются, поэтому сборщик мусора может сканировать каждый объект, чтобы проверить, не был ли он удален. Если приложение представляет собой веб-проект, все запросы останавливаются до завершения gc, и это приведет к тому, что ваш веб-проект не сможет работать в моненте.

0
fleture