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

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

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

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

Я бы настоятельно рекомендовал прочитать через документы сборку мусора Java HotSpot для более подробной информации о сборке мусора.

Ответ 6

System.gc() реализуется VM, и то, что он делает, является специфичным для реализации. Например, исполнитель мог просто вернуться и ничего не делать.

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

Ответ 7

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

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

Ответ 8

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

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

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

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

Ответ 9

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

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

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

Ответ 10

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

Ответ 11

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

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

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

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

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

Ответ 12

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

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

Ответ 13

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

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

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

Ответ 14

Короче:

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

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

// 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();

Ответ 15

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

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

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

Ответ 16

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

Ответ 17

вы можете видеть вызовы System.gc() из разных источников, а не только из исходного кода вашего приложения. Таким образом, поиска строки кода вашего приложения System.gc() недостаточно, чтобы определить, выполняет ли ваше приложение вызовы System.gc(). Таким образом, возникает проблема: как определить, выполняются ли вызовы System.gc() во всем вашем стеке приложений?

Вот где GC журналы пригодятся. Включите журналы GC в вашем приложении. На самом деле, желательно постоянно поддерживать журнал GC на всех ваших производственных серверах, поскольку это помогает вам устранять неполадки и оптимизировать производительность приложений. Включение журналов GC добавляет незначительные (если вообще наблюдаемые) накладные расходы. Теперь загрузите ваш журнал GC в инструмент анализа журналов сбора мусора, такой как GCeasy, HP JMeter,…. Эти инструменты создают подробный отчет об анализе сбора мусора.

Подробнее: Недостатки вызова System.gc()

Ответ 18

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