Есть ли способ запланировать сборку полного мусора в Java?

У меня есть приложение, работающее по расписанию 24x6. В настоящее время, после работы в течение нескольких дней, полный GC выполняется автоматически - и обычно в течение насыщенной части дня, что отрицательно влияет на время ответа пользователя.

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

Информация о версии:

Java (TM) SE Runtime Environment (сборка 1.6.0_11-b03)
Java HotSpot (TM) Server VM (сборка 11.0-b16, смешанный режим)

Дополнительно -

  • Незначительные GC работают примерно каждые 10-15 секунд. Но они не освобождают достаточное количество ОЗУ, чтобы получить приложение через всю неделю. Когда Full GC действительно происходит, почти 50% кучи освобождается.
  • Что касается вышеизложенного, вызов System.gc() не означает, что любой из следующих GCs будет иметь полную форму, необходимую для освобождения этих больших патронов памяти. Да, он включен (или не отключен, в зависимости от того, как вы читаете параметр -XX).
  • Я уже играл с несколькими настройками GC CMS, что очень помогло, но не решило проблему. Первоначально он бросал OOMs два-три раза в неделю.
  • Я хочу остановить бесконечные циклы:
    • постоянно добавляя в кучу пространство, которое может продолжаться так долго
    • постоянная настройка и тестирование настроек GC - это уже давно минус возвращение
  • Я не хочу рассматривать это как машину NT и отказываться от нее в ночное время. Активные пользовательские сессии в течение всей ночи, и подпрыгивание приложения означало бы потеря данных сеанса.

Чтобы быть более конкретным, я больше ищу технику, чтобы гарантировать, что будет выполнен полный GC, а не простой метод/функция для вызова для его запуска.

На данный момент я смотрю на изменение процентного порога, используемого CMS, чтобы определить, когда требуется полный GC.

Спасибо за любую помощь.

Ответ 1

jmap -histo:live <PID> заставит Full GC как "побочный эффект" найти все живые объекты. Вы можете запланировать его переработку процессов JVM в нерабочее время.

Ваш JVM build 1.6.0_11-b03 довольно древний, но jmap должен поддерживаться на всех 1.6 JVM HotSpot.

Ответ 2

Нет.

System.gc() предлагает GC, что вы хотели бы коллекцию.

Кроме того, в течение спокойного периода, вероятно, очень мало мусора, и поэтому вызов System.gc() не делает многого.

Во время пикового времени существует, по-видимому, больше активности и, следовательно, создается больше мусора - следовательно, потребность в коллекции.

Должно быть очевидно, что вы не можете откладывать сбор таким упрощенным способом. JVM будет собирать, когда это необходимо.

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

Вы должны изучить настройку сборщика CMS - это довольно хорошая статья об основах системы GC на Java. В Java 7 есть новый G1GC, который может быть или не быть лучше.

Вы должны найти способ имитации условий нагрузки и попробовать разные параметры GC, CMS GC имеет множество параметров настройки и настройку, это несколько темное искусство...

Это несколько более интересная статья по настройке и бенчмаркингу GC.

Ответ 3

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

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

Удостоверьтесь, что у вас есть какая-то логика, которая обнаруживает GC и останавливает процесс.

Ответ 4

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