Когда собирать мусор

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

System.gc();

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

Вчера я решил использовать довольно полезную часть программного обеспечения под названиемFindBugs который сканирует ваш код и сообщает о проблемах, которые могут вызвать ошибки или вообще не рекомендованные стратегии. Проблема в том, что об этом фрагменте кода, о котором я упоминал, сообщили. Описание таково:

... forces garbage collection; extremely dubious except in benchmarking code

И это продолжает уточнять:

Code explicitly invokes garbage collection. Except for specific use in benchmarking, this is very dubious.

In the past, situations where people have explicitly invoked the garbage collector in routines such as close or finalize methods has led to huge performance black holes. Garbage collection can be expensive. Any situation that forces hundreds or thousands of garbage collections will bring the machine to a crawl.

Итак, мой вопрос:Is it NOT OK to programmatically call the garbage collector in such a case? My code only calls it once and the method that it is in gets used rarely. And if it is not OK to call it then what should you do in a case where you need as much memory as possible before doing a very memory intensive operation and you need to free as much memory as posible prior to it?

 Tom Hawtin - tackline18 июл. 2009 г., 14:40
В этом случае вы, вероятно, сериализуете производительность. Если вы позволите GC решить, когда запускать, он вполне может работать, когда приложение блокирует ввод-вывод.
 KitsuneYMG19 июл. 2009 г., 05:38
Q: Когда вызывать System.gc (). Никогда
 Savvas Dalkitsis19 июл. 2009 г., 13:52
Вау, это было полное понимание. Я полностью понимаю, почему я никогда не должен называть gc вашим ответом. Большое спасибо.

Ответы на вопрос(8)

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

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

нет. Неуместно вызывать System.gc (). Однако у меня было несколько случаев, когда это имело смысл.

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

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

что большие объекты могут быть обработаны как можно раньше. То есть установите переменные в нуль и / или пусть они выпадают из области видимости Это помогает!

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

 18 июл. 2009 г., 16:50
Вы никогда не "знаете" наверняка у вас неорганизованная раскладка памяти. GC мог просто бежать, насколько вы знаете. & Quot; метка & quot; часть разметки занимает ресурсы и время, даже если вы ничего не собираете. Вот почему почти всегда есть чистый отрицательный или (в лучшем случае) случай безубыточности, чтобы попытаться перехитрить GC.
 18 июл. 2009 г., 14:25
Проблема в том, что это только после того, как он пытается что-то выделить. Если вы находитесь в ситуации, когда вы "знаете" что у вас очень дезорганизованная структура памяти, и вы "знаете" вам требуется большой блок памяти, вы можете просто вызвать GC несколькими инструкциями ранее.
 18 июл. 2009 г., 19:06
Среда выполнения и gc могут свободно изменять и перемещать объекты в памяти, когда бы это ни казалось (объекты больше похожи на указатель на указатель, если вы пришли из мира Си), вы вряд ли когда-нибудь узнаете об этом. что у вас неорганизованный макет.
Решение Вопроса

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

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

btw: Вызов System.gc () рекомендует виртуальной машине выполнить «полную» операцию. или "большой" коллекция, что означает, что все потоки будут остановлены в ближайшее время. В противном случае он, вероятно, сделает «маленьким» сборки мусора, которые не останавливают все потоки.

Запустите вашу программу с -verbose: gc, чтобы увидеть, сколько байт собрано.

Здесь также есть много технической информации по сбору мусора: http://java.sun.com/developer/technicalArticles/Programming/GCPortal/

 19 июл. 2009 г., 05:41
-1 для НЕУДАЧИВОГО чтения javadoc на System.gc (), как сказал Адриан, это ничего не заставляет.stackoverflow.com/questions/1147511/… для реального форсирования gc
 18 июл. 2009 г., 15:55
System.gc () не «заставляет» что-нибудь. ВМ может игнорировать это. Формулировка в Javadoc "Вызов метода gc"suggests что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов & quot; (акцент мой)

которые я постараюсь не повторять.

Если у вас действительно возникают проблемы с GC, например, полная остановка вашего приложения на секунду, сделайте следующее: 1. убедитесь, что нет никаких вызовов System.gc (); 2. проверить различные варианты настройки gc. Таких вокруг множество, и они гораздо полезнее, чем форсировать gc.

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

Что вы должны сделать в этом случае, это профилировать код. Запустите его несколько раз, посмотрите, какие результаты вы получите.

запускается цикл GC, и распределение повторяется.

Ваш ответ на вопрос