Вот пример Java8
Симуляция окружающей среды GC
Сначала мы даем следующий код для запуска GC
public static void main(String[] args) {
// 每100毫秒创建100线程,每个线程创建一个1M的对象,即每100ms申请100M堆空间
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
try {
// 申请1M
byte[] temp = new byte[1024 * 1024];
Thread.sleep(new Random().nextInt(1000)); // 随机睡眠1秒以内
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}, 1000, 100, TimeUnit.MILLISECONDS);
}
Сценарий, который мы хотим смоделировать, заключается в том, что молодое поколение постоянно является молодым GC, а некоторые объекты повышаются до старого поколения, запуская полный GC, когда старому поколению не хватает места.
Логика программы: каждые 100 миллисекунд создается 100 потоков, и каждый поток создает объект размером 1M, то есть на каждые 100 мс применяется 100M пространства кучи. Причина, по которой каждый поток спит случайным образом в течение 1 с, заключается в том, чтобы предотвратить смерть объектов и гарантировать, что некоторые объекты могут быть переведены в старость, что может лучше запускать Young GC и Full GC.Обратите внимание, что если это время ожидания слишком велико, это вызовет OOM. Если он маленький, сложно запустить ПОЛНЫЙ GC.
Объяснение параметров виртуальной машины
Запустите процесс Java: java -Xms200m -Xmx200m -Xmn100m -verbose:gc -XX:+PrintGCDetails -Xloggc:./gc.log -XX:+PrintGCDateStamps -jar demo-0.0.1-SNAPSHOT.jar
-Xms200m -Xmx200m Мин./макс. память кучи 200M
-Xmn100m младшее поколение памяти 100M
-verbose:gc включить ведение журнала GC
-XX:+PrintGCDetails -Xloggc:./gc.log -XX:+PrintGCDateStamps Введите данные журнала GC в gc.log
jmap-анализ
jcmd получает идентификатор нашего Java-процесса: 6264.
jmap -heap 6264 Просмотр информации о куче
В первый раз, когда мы проверили, мы обнаружили, что площадь Эдема составляет 98 м, а S0 и S1 — 1 м.
Вторая проверка, площадь Эдема 99м, S0, S1 0.5м
Соотношение площади Эдема и площади Выживших меняется динамически, а не 8:1:1 по умолчанию.
Получается, что мы используем дефолтную комбинацию сборщика мусора Parallel Scavenge+Parallel Old, и под этим сборщиком по умолчанию включено -XX:+UseAdaptiveSizePolicy, то есть соотношение площади Эдема к площади Survivor будет адаптивно меняться в соответствии с Ситуация с ГК.
Добавляем параметры, отключаем адаптацию молодого поколения и устанавливаем соотношение молодого поколения 8:1:1
-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8
Кроме того, чтобы как можно быстрее запустить ПОЛНУЮ сборку мусора, мы добавили параметры виртуальной машины.
-XX:MaxTenuringThreshold=10
Возраст повышения изменен с 15 по умолчанию на 10, что упрощает переход объектов из молодого поколения в старое поколение.
Перезапустите виртуальную машину для просмотра jmap
молодое поколение
-
80 миллионов в районе Эдема использовали 51 миллион, а текущий уровень использования составляет 63,8%
-
10 млн в области S0 использовали 0,43 млн, коэффициент использования составляет 4,37%
-
Скорость использования области S1 10M пуста
старость
- 100M использовали 18,39M, уровень использования 18,9%
Анализ содержимого журнала GC
Посмотрите на журнал GC gc.log, который мы выводим, и выберите два из них.
2019-06-09T02:55:30.993+0800: 330.811: [GC (Allocation Failure) [PSYoungGen: 82004K->384K(92160K)] 184303K->102715K(194560K), 0.0035647 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 2019-06-09T02:55:30.997+0800: 330.815: [Full GC (Ergonomics) [PSYoungGen: 384K->0K(92160K)] [ParOldGen: 102331K->5368K(102400K)] 102715K->5368K(194560K), [Metaspace: 16941K->16914K(1064960K)], 0.0213953 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
Young GC
[GC (Allocation Failure) [PSYoungGen: 82004K->384K(92160K)] 184303K->102715K(194560K), 0.0035647 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
объяснять:
-
GC GC молодого поколения: [Pre-Pred Pred Production 80,08M-> GC 0.37M (общее количество молодого поколения 90 м)] GC Front Counce 179,98M-> GC 10,3 м (куча общего размера 190m), время]
-
Суммарный размер молодого поколения 90М вместо 100М. Тут я понимаю, что текущая максимальная заявка для молодого поколения 90М
-
100M*80%=80M - это площадь Эдема.
-
80M*80% = 64M Район Эдема по умолчанию занимает более 80%, то есть 64M вызовет YoungGC
Full GC
[Full GC (Ergonomics) [PSYoungGen: 384K->0K(92160K)] [ParOldGen: 102331K->5368K(102400K)] 102715K->5368K(194560K), [Metaspace: 16941K->16914K(1064960K)], 0.0213953 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
объяснять:
-
[Молодое поколение до GC 0.375M->Молодое поколение после GC 0M (общий размер молодого поколения 90M)][Старое поколение до GC 99.93M->Старое поколение после GC 5.24M (Общий размер старого поколения 100M)]Куча перед GC 100,3M -> После кучи GC 5,24M (общий размер кучи 190M), [область метаданных: 16,5 до GC, 16,5 после GC (общий размер области метаданных 1040M)], использованное время]
-
Можно предположить, что причиной этого FullGC является отсутствие места для продвижения молодого поколения к старому поколению.
Анализ с помощью инструментов визуализации
Здесь мы используемgceasy.io/Проанализируйте это
(1) Подсчитайте молодое поколение, старое поколение, а также максимальное свободное пространство и пиковое значение области метаданных.Здесь размер области метаданных не настроен в параметрах нашей виртуальной машины, поэтому значение по умолчанию составляет 1040 МБ.
(2) Статистика пропускной способности, средней задержки GC, максимальной задержки и интервала задержки
(3) Анализ размера кучи в режиме реального времени, красная позиция показывает, что произошел FullGC, что привело к резкому падению общей кучи.
(4) Статистика общего объема пространства и времени GC
(5) Различное время GC, время GC, общее количество GC и другие индикаторы
Суммировать
Анализ журнала сборщика мусора может помочь нам макроскопически отслеживать операции сборщика мусора. С одной стороны, если частый FullGC будет иметь серьезные проблемы с производительностью (STW), с другой стороны, если GC слишком частый, то есть GC занимает большую долю нормальной работы системы и пропускная способность низкий, что в определенной степени является пустой тратой ресурсов производительности. Если в системе есть проблема с производительностью, согласно анализу GC различных показателей в качестве эталона, мы также можем внести некоторые коррективы в параметры программы или виртуальной машины.