Умная сборка мусора? - PullRequest
       4

Умная сборка мусора?

3 голосов
/ 01 июня 2011

Вы можете собрать мусор в Java, просто вызвав System.gc(), но иногда это "останавливает" приложение. Это плохая идея собирать мусор, как это, и избегать киосков:

new Thread(new Runnable() {
   public void run() { 
      System.gc(); 
   }
}).start();

Или это может привести к еще большим проблемам?

Ответы [ 6 ]

15 голосов
/ 01 июня 2011

Перво-наперво: НЕ ПРИЗЫВАЙТЕ ГУ GC

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

ГК знает, что делает (большую часть времени ...)

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

GC не всегда заботится о том, что вы говорите

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

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

Другие рекомендации

Охота и убийство (плохо) Явное GC

  • включить -XX:+DisableExplicitGC (если вашJVM поддерживает это), чтобы предотвратить эти безумные призывы к причинению какого-либо вреда (благодарность Фредрику в комментариях)
  • посмотрите в вашей любимой IDE или grep для вызовов на System.gc() и ее эквиваленты и избавьтесь от них.

Найди другой путь

См. Ответ Grooveek для других полезных советов (например, использование WeakReference s).

Экспериментируйте с другими GC и настраивайте свою виртуальную машину для своего приложения

В зависимости от вашего варианта использования, возможно, могут помочь эксперименты с другими реализациями GC: CMC, G1, ParallelGC и т. Д. Если вы хотите избежать «зависаний», у меня были очень хорошие результаты с G1 с момента его появления в последней версии.Java SE 6 обновляется и, начиная с выпуска Java 7, запускает интенсивные корпоративные приложения в течение длительных периодов.

Просто имейте в виду, что настройка JVM - очень сложное искусство.

Дополнительная литература

Вы можете пролистать их для более подробной информации:

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

3 голосов
/ 01 июня 2011

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

2 голосов
/ 01 июня 2011

Я не могу разбить ясность и силу @haylem ответа, извините.Но позвольте мне добавить, что в Java есть много (лучших) способов управления памятью.Например, есть WeakReference и коллекции, которые их обрабатывают, например WeakHashMap .Это детерминистический способ обработки памяти, хотя явные вызовы GC - нет, согласно javadoc

Calling the gc method suggests that the Java Virtual Machine expend effort toward 
recycling unused objects in order to make the memory they currently occupy available 
for quick reuse. When control returns from the method call, the Java Virtual Machine 
has made a best effort to reclaim space from all discarded objects.
0 голосов
/ 01 июня 2011

Как уже говорили другие, звонить System.gc() обычно ошибка.(Не всегда ...)

Если предположить, что у вас есть один из тех редких вариантов использования, в которых вызов System.gc() может быть полезным, есть дваРассмотрим следующие случаи:

  • Если ваша JVM использует классический коллектор "Stop the World", то запуск его в отдельном потоке не будет иметь значения.GC останавливает все потоки приложений на время.

  • Если ваша JVM работает с параллельным сборщиком, то запуск его в отдельном потоке может быть хорошей идеей.Это правда, что у всех сборщиков есть фаза, на которой все потоки останавливаются, но при вызове System.gc() задокументировано возвращение после «Виртуальная машина Java сделала все возможное, чтобы освободить пространство от всех отброшенных объектов» ,Поэтому запуск его в отдельном потоке позволит текущему потоку делать что-то еще.Однако вы должны быть осторожны, чтобы не запускать несколько потоков, каждый из которых вызывает System.gc();т. е. код, отвечающий за запуск потока, должен отслеживать любые предыдущие потоки GC.

0 голосов
/ 01 июня 2011

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

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

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

0 голосов
/ 01 июня 2011

Помимо того, что уже было сказано, вся идея ужасно ошибочна, потому что вы, к сожалению, упускаете одну важную деталь:

Пока запущен полный сборщик мусора, приложение будет остановлено! (по крайней мере, в настоящее время на современной виртуальной машине Hotspot - и что еще вы будете использовать?)

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

...