Что означает "GC--" в журнале сбора мусора java?

Мы включили подробный журнал GC, чтобы отслеживать известную утечку памяти и получили следующие записи в журнале:

...
3607872.687: [GC 471630K->390767K(462208K), 0.0325540 secs]
3607873.213: [GC-- 458095K->462181K(462208K), 0.2757790 secs]
3607873.488: [Full GC 462181K->382186K(462208K), 1.5346420 secs]
...

Я понимаю первую и третью из них, но что означает "GC--"?

Ответ 1

Я получил такие строки в моем выпуске gc:

44871.602: [GC-- [PSYoungGen: 342848K->342848K(345600K)] 961401K->1041877K(1044672K), 0.1018780 secs] [Times: user=0.16 sys=0.00, real=0.11 secs]

Я прочитал ответ Yishai, и это будет иметь смысл, но я хотел увидеть его для себя в исходном коде Java GC, когда JVM печатает "-" в журнале GC и почему.

Потому что, насколько мне известно, "Parallel Scavenge" из Young Gen - это GC-стоп-стоп, поэтому там не может быть никаких объектов, созданных параллельно для этого GC. (см. https://blogs.oracle.com/jonthecollector/entry/our_collectors)

Вы можете найти это в исходном коде jdk (см. http://hg.openjdk.java.net/jdk7/jdk7) g1CollectedHeap.cpp и psScavenge.cpp

jdk7-ee67ee3bd597/hotspot/src/share$ egrep -h -A2 -B5 -r '"\-\-"' *
# G1 Collector
if (evacuation_failed()) {
  remove_self_forwarding_pointers();
  if (PrintGCDetails) {
    gclog_or_tty->print(" (to-space overflow)");
  } else if (PrintGC) {
    gclog_or_tty->print("--");
  }
}
--
# Parallel Scavenge Collector
promotion_failure_occurred = promotion_failed();
if (promotion_failure_occurred) {
  clean_up_failed_promotion();
  if (PrintGC) {
    gclog_or_tty->print("--");
  }
}

Причина для GC-- с коллектором параллельных сборщиков

Молодой GC столкнулся с неудачей продвижения (см. http://mail.openjdk.java.net/pipermail/hotspot-gc-use/2010-March/000567.html):

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

"Недостаточно места" не обязательно означает, что в нем недостаточно места, но старое пространство сильно фрагментировано (см. http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

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

Эти два параметра JVM могут помочь вам проанализировать фрагментацию кучи (см. http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

-XX:+PrintPromotionFailure
-XX:PrintFLSStatistics=1

Причина для GC-- с коллектором G1

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

Я не знаю, отвечает ли сборщик G1 на отказ эвакуации с полным GC или нет.

Ответ 2

Я получил следующее из здесь:

Первые две строки указывают, что вы две небольшие коллекции и один крупный один. Числа до и после стрелка указывает совокупный размер живые объекты до и после мусора коллекции, соответственно. После незначительных коллекции включают в себя объекты которые не обязательно живы, но не могут быть восстановлены, потому что они живы или потому, что они находятся в пределах или ссылаются на поколение. Число в скобки с общим доступным пространство, не считая пространства в постоянное поколение, которое является общая куча минус одна Формат для основная коллекция в третьей строке похож. Флаг -XX: + PrintGCDetails печатает дополнительную информацию о коллекциях. дополнительная информация, напечатанная с этот флаг может изменяться с каждой версии виртуальной машины. Дополнительный выход с -XX: + PrintGCDПодробнее указывается флаг с учетом потребностей разработка Java Virtual Машина. из оставшихся в живых. небольшая коллекция заняла около четверти секунды.

Ответ 3

Собственно, после встречи с этим в наших журналах, у меня есть альтернативное объяснение, которое, по-видимому, более тесно связано с фактами.

В этом примере вы заметите, что Full GC следует за этой странной минорной линией GC. Я могу подтвердить, что это всегда так, когда оно появляется в наших журналах. Вы также можете увидеть, что начальный и конечный размеры Young Gen равны, и я могу снова подтвердить, что это всегда так.

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

Ответ 4

Это не в FAQ по Java GC

http://java.sun.com/docs/hotspot/gc1.4.2/faq.html

Ничего подобного не упоминается на странице примеров Java GC

http://java.sun.com/docs/hotspot/gc1.4.2/example.html

Я никогда раньше этого не видел.

У вас есть специальный сборщик мусора? Какую виртуальную машину вы используете? Всегда ли это происходит до полного GC? Вы вызываете System.gc()?

Ответ 5

Yishai сказал в комментариях:

Учитывая временные метки и объемы памяти, я предполагал, что он выполнил сборку мусора, но потерял доступную память (поскольку другие объекты были созданы параллельно)