Вызов System.gc () явно? - PullRequest
       21

Вызов System.gc () явно?

15 голосов
/ 24 января 2011

Говорят, что мы не можем форсировать процесс garbage collection в Java.
В конце концов, это нить демона.

Но все же иногда, почему мы вызываем функцию System.gc( ); явно?
Стоит ли это называть? Любые "за" и "против"?
Если этот метод бесполезен во многих ситуациях, почему этот метод не устарел в Java?

PS: объяснение с примером будет полезно

Ответы [ 8 ]

9 голосов
/ 24 января 2011

На мой взгляд, лучше всего думать о методе System.gc() как о «подсказке» виртуальной машине, что должна выполняться сборка мусора.Тем не менее, так же, как большой процент «оптимизаций», которые люди думают, что они выполняют, обычно лучше просто позволить системе позаботиться обо всем самостоятельно.Системы развиваются и т. Д. И т. Д. И т. Д. Есть еще некоторые случаи, когда разработчик может знать об этом лучше, и пример использования для него, вероятно, очень похож на то, почему некоторый код все еще пишется на ассемблере (в большинстве случаев компилятор лучше, но в некоторых случаях - или с несколькими разработчиками - люди действительно могут писать более эффективный код).

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

8 голосов
/ 24 января 2011

Вы ответили на половину своего вопроса: оно того стоит? Нет, потому что вы не можете заставить это.

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

Это почти английский EULA для "вы можете попробовать, но мы оба знаем результат". :)

Кроме того, серверы приложений могут (и часто будут) отключать его, используя параметр командной строки -XX:-DisableExplicitGC.

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

7 голосов
/ 24 января 2011

В: почему мы вызываем System.gc (); функция явно?

A: Потому что кто-то написал плохой код.

Я думаю, что большинство людей согласятся, что вы не должны звонить System.gc() явно.

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

Если вам нужна дополнительная информация, я бы посоветовал прочитать ответы на:

Java - почему плохая практика вызывать System.gc?

3 голосов
/ 24 января 2011

В некоторых случаях вызов System.gc () полезен:

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

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

2 голосов
/ 25 января 2011

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

вот код из java.nio.Bits

static void reserveMemory(long size) {

    synchronized (Bits.class) {
        if (!memoryLimitSet && VM.isBooted()) {
            maxMemory = VM.maxDirectMemory();
            memoryLimitSet = true;
        }
        if (size <= maxMemory - reservedMemory) {
            reservedMemory += size;
            return;
        }
    }

    System.gc();
    try {
        Thread.sleep(100);
    } catch (InterruptedException x) {
        // Restore interrupt status
        Thread.currentThread().interrupt();
    }
    synchronized (Bits.class) {
        if (reservedMemory + size > maxMemory)
            throw new OutOfMemoryError("Direct buffer memory");
        reservedMemory += size;
    }

Сон необходим для фактического запуска финализатора (или попытки запуска). У очистителей обычно есть ускоренная процедура в высокоприоритетном потоке финализатора.

0 голосов
/ 06 января 2014

Это явно anti-pattern to use System.gc(), хотя мы используем его, чтобы предложить JVM для уборки мусора, но JVM решает, будет ли он или нет, он дополнительно налагает некоторые критерии, на которые он смотрит, когда происходит System.gc(). Если критерий следует, то он действует; в противном случае нет.

0 голосов
/ 24 января 2011
It is said that we cannot force the garbage collection process in java.

Это очень распространенное мнение, которое совершенно неверно.

Некоторые приложения делают это на регулярной основе, а некоторые даже имеют блестящие кнопки, которые вы можете нажимать, которые делают действительно выполнить сбор.Другими словами: они не «намекают» GC, что они хотели бы, чтобы GC запускал, но они действительно заставляют GC.

Так что вера и популярна, и ошибочна.Что менее популярно, так это знания о том, как вы на самом деле запускаете такой сборщик мусора, как показывает уникальный (и очень расплывчатый) ответ на мой вопрос, поставленный в 6 раз выше:Вы действительно используете GC, используя ForceGargabeCollection JVMTI?

0 голосов
/ 24 января 2011

О какой версии Java мы здесь говорим? В 6 я бы никогда не назвал это явно. Как правило, сборщик мусора достаточно хорош, чтобы знать, когда лучше всего очистить ресурсы, и у него достаточно настраиваемых параметров виртуальной машины. Я, конечно, никогда не чувствовал необходимости называть это в коде, и я бы сказал, что если вы не делаете что-то действительно странное (или демонстрирующее использование ресурсов), то лучше этого не делать. Если вам нужно позвонить, я бы сказал, что вы сделали что-то плохое или неправильное в другом месте.

Если мы говорим о работе с Java 1.4 или ранее, иногда я нахожу, что она нуждается в помощи. Нет примеров, которые можно было бы передать (извините), но я помню, что мне нужно было дать подсказку, чтобы избежать ужасной задержки, когда он решил в конечном итоге запустить. С тем же кодом на 6 проблема исчезла, и ее вызов почти не изменился.

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

Так что да, он все еще используется в коде - но в подавляющем большинстве случаев это вообще не очень хорошая практика.

...