В каких случаях разработчику важно понимать механизм сборки мусора в Java?

«В каких случаях разработчику важно понимать механизм сборки мусора в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Понимание механизма сборки мусора (GC) критично для разработчика в следующих сценариях:

  1. Оптимизация производительности: Выбор подходящего сборщика под конкретные требования приложения (latency, throughput).
  2. Предотвращение утечек памяти: Выявление и устранение ситуаций, когда объекты не освобождаются, хотя больше не нужны.
  3. Настройка JVM: Корректная настройка параметров кучи (-Xmx, -Xms) и сборщика (например, -XX:+UseG1GC).
  4. Работа с кэшами и пулами: Использование WeakReference, SoftReference для предотвращения утечек в кэшах.

Практический пример утечки памяти:

import java.util.ArrayList;
import java.util.List;

public class MemoryLeakExample {
    // Статическое поле удерживает все добавленные объекты
    private static final List<byte[]> LEAKING_LIST = new ArrayList<>();

    public static void main(String[] args) {
        while (true) {
            // Объекты добавляются, но никогда не удаляются
            LEAKING_LIST.add(new byte[10_000]);
        }
    }
}

Выбор сборщика:

  • G1GC (Garbage-First): Баланс latency и throughput, рекомендуется по умолчанию (Java 9+).
  • ZGC / Shenandoah: Для сверхнизких пауз (low-latency приложения).
  • Parallel GC: Для максимальной пропускной способности (throughput), где длительные паузы допустимы.

Best Practice: Профилируйте приложение с помощью jvisualvm, jconsole или профилировщиков (YourKit, JProfiler) для анализа работы GC и потребления памяти.