сеньорчикОткрыть в Telegram
← все вопросывопросы для собеседований · JVM и сборка мусора

Вопросы по JVM на собеседовании

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

77 вопросов в банке·5 подтем·ниже разбор 9

Из чего состоит тема

Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.

Разборы подтем

Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.

Примеры вопросов с разбором

  1. #class_loading1 / 9
    Как устроена модель делегирования загрузчиков классов (parent delegation)?
    A)Загрузчик сначала делегирует загрузку родителю и грузит сам, только если тот не смог
    B)Загрузчик сам грузит класс и лишь потом сообщает родителю, какой класс был загружен
    C)Все классы грузит один системный загрузчик, иерархии загрузчиков в Java практически нет
    D)Дочерний и родительский загрузчики грузят каждый класс параллельно, а затем сверяют результаты
    показать ответ и разбор
    +A)Загрузчик сначала делегирует загрузку родителю и грузит сам, только если тот не смог

    // разбор: При запросе класса загрузчик СНАЧАЛА делегирует его родителю (и так вверх до bootstrap), и грузит сам только если ни один родитель класс не нашёл. Иерархия: Bootstrap (ядро JDK) → Platform → Application (classpath). Делегирование гарантирует, что базовые классы (java.lang.String) грузит именно bootstrap — их нельзя подменить своим java.lang.String с classpath (безопасность и уникальность). Идентичность класса = его имя + загрузчик.

  2. #diagnostics_leaks2 / 9
    Что из перечисленного — типичная причина утечки памяти в Java?
    A)Бесконечно растущая static-коллекция/кэш без вытеснения
    B)Слишком частые вызовы сборщика мусора, из-за которых объекты не успевают освобождаться вовремя
    C)Использование локальных переменных в методах — они остаются в куче и после выхода из метода
    D)Создание большого числа короткоживущих объектов внутри цикла — они переполняют старое поколение
    показать ответ и разбор
    +A)Бесконечно растущая static-коллекция/кэш без вытеснения

    // разбор: Классические утечки — там, где ссылки НЕ отпускаются, хотя объект уже не нужен: статические коллекции/кэши, растущие без ограничения; забытые слушатели/колбэки/подписки; незачищенные ThreadLocal (особенно в пуле потоков); удержанные загрузчики классов. GC такие объекты не собирает — они достижимы от корней. Лечение: ограниченные кэши (LRU/WeakHashMap), обязательная отписка, очистка ThreadLocal, аудит heap dump. Короткоживущие объекты, наоборот, — забота дешёвого minor GC.

  3. #garbage_collection3 / 9
    На каком принципе строится поколенческая (generational) сборка мусора?
    A)Большинство объектов умирает молодыми — молодое поколение чистят часто и быстро
    B)Объекты сортируются по размеру: крупные собираются часто, а мелкие — раз в несколько часов работы
    C)Все объекты живут одинаково долго, поэтому куча делится на равные части и чистится строго по кругу
    D)Старые объекты собираются первыми, так как именно они чаще всего становятся ненужными приложению
    показать ответ и разбор
    +A)Большинство объектов умирает молодыми — молодое поколение чистят часто и быстро

    // разбор: Поколенческая сборка опирается на эмпирику: ПОДАВЛЯЮЩЕЕ большинство объектов живёт очень недолго («умирают молодыми»). Поэтому кучу делят на young generation (Eden + два Survivor) и old generation. Молодое поколение собирают часто и быстро (minor GC), переживших несколько раз объектов «повышают» в старое; старое собирают реже и дороже (major/full GC). Так минимизируется объём работы: не сканировать всю кучу каждый раз.

  4. #jvm_execution4 / 9
    Как JVM исполняет байткод?
    A)Сначала интерпретирует, а горячие участки компилирует в машинный код JIT-ом
    B)Компилирует весь байткод в машинный код заранее при старте, поэтому первая же итерация уже оптимальна
    C)Только интерпретирует байткод построчно, никакой компиляции в нативный код в JVM не происходит
    D)Переводит байткод обратно в исходный.java и запускает его через встроенный интерпретатор языка
    показать ответ и разбор
    +A)Сначала интерпретирует, а горячие участки компилирует в машинный код JIT-ом

    // разбор: HotSpot исполняет байткод СМЕШАННО: сначала интерпретирует (быстрый старт), одновременно профилируя исполнение, а «горячие» (часто вызываемые) методы компилирует JIT-ом в оптимизированный машинный код прямо во время работы. Это адаптивная оптимизация: JIT знает реальные пути исполнения и оптимизирует агрессивнее статического компилятора, при необходимости деоптимизируя обратно. Поэтому пиковой скорости приложение достигает не сразу, а после «прогрева».

  5. #memory_model5 / 9
    Где размещаются объекты и где — локальные примитивы/ссылки в JVM?
    A)Объекты — в куче (heap); локальные примитивы и ссылки — в стеке потока
    B)Всё подряд — и объекты, и локальные переменные — хранится в общей куче, стек в Java не используется
    C)Объекты лежат в стеке каждого потока, а куча отведена только под загруженные классы и их методы
    D)Объекты и локальные переменные размещаются в metaspace, а куча используется лишь под строки-литералы
    показать ответ и разбор
    +A)Объекты — в куче (heap); локальные примитивы и ссылки — в стеке потока

    // разбор: Куча (heap) — общая для всех потоков область, где живут ВСЕ объекты (включая массивы). Стек — свой у каждого потока: в его кадрах лежат локальные примитивы и ССЫЛКИ на объекты (сами объекты — в куче). Метаданные классов — в metaspace (нативная память). Поэтому объект доступен из разных потоков (общая куча), а локальные переменные потоко-локальны. Управляет кучей сборщик мусора; кадр стека освобождается при выходе из метода.

  6. #class_loading6 / 9
    Какие есть встроенные загрузчики классов в современной JVM?
    A)Только один загрузчик — системный; остальные существовали лишь в очень ранних версиях Java
    B)Bootstrap, Platform и Application (system) — по иерархии
    C)Compile-loader и Runtime-loader: первый грузит классы при компиляции, второй — при исполнении
    D)По одному загрузчику на каждый пакет приложения, они создаются автоматически под каждый пакет
    показать ответ и разбор
    +B)Bootstrap, Platform и Application (system) — по иерархии

    // разбор: Стандартная иерархия (с Java 9): Bootstrap загружает ядро JDK (java.base); Platform — платформенные модули; Application (он же System) — классы приложения с classpath/module-path. Раньше между Bootstrap и App был Extension ClassLoader — его заменил Platform. Приложения могут добавлять свои URLClassLoader (плагины, серверы приложений). Именно на нестандартных загрузчиках чаще возникают утечки metaspace и конфликты версий классов.

  7. #diagnostics_leaks7 / 9
    О чём говорит OutOfMemoryError: Java heap space?
    A)Закончилось место на жёстком диске, куда JVM сбрасывает объекты из переполненной оперативной памяти
    B)Куче не хватает места: утечка, малый -Xmx или реально большой объём данных
    C)Переполнился стек одного из потоков из-за слишком глубокой рекурсии в коде приложения
    D)Metaspace исчерпан загруженными классами, и новые классы загрузить не получится
    показать ответ и разбор
    +B)Куче не хватает места: утечка, малый -Xmx или реально большой объём данных

    // разбор: «OutOfMemoryError: Java heap space» — сборщик не смог освободить достаточно места в куче под новые объекты. Причины: утечка (объекты копятся, будучи достижимыми), слишком маленький -Xmx под реальный объём, или объективно большой набор данных/пиковая нагрузка. Диагностика: снять heap dump (-XX:+HeapDumpOnOutOfMemoryError), проанализировать в MAT/VisualVM кто держит память, посмотреть GC-логи. Это ОТДЕЛЬНАЯ ошибка от Metaspace-OOM, StackOverflowError и «unable to create native thread».

  8. #garbage_collection8 / 9
    Какой сборщик мусора используется по умолчанию в современной JVM (Java 9+)?
    A)Serial GC — однопоточный сборщик, оптимальный для серверов с большими кучами и многими ядрами
    B)G1 GC
    C)CMS (Concurrent Mark-Sweep) — он остаётся дефолтным и рекомендуемым выбором в новых версиях
    D)Виртуальный сборщик, который не освобождает память, а лишь помечает объекты для ручной очистки
    показать ответ и разбор
    +B)G1 GC

    // разбор: С Java 9 сборщик по умолчанию — G1 (Garbage-First): регионный, стремится укладываться в целевую паузу, хорошо подходит для средних-больших куч. Serial — для маленьких приложений/одного ядра; Parallel — на максимум throughput; CMS удалён. Для сверхнизких пауз (сотни ГБ, sub-ms) есть ZGC и Shenandoah. Выбор GC — компромисс между длиной пауз и пропускной способностью, задаётся флагами (-XX:+UseZGC и т.п.).

  9. #jvm_execution9 / 9
    Что такое tiered compilation (C1 и C2)?
    A)Разделение кода на два потока: C1 исполняет чётные методы, а C2 — нечётные, ради параллелизма
    B)Многоуровневая компиляция: C1 быстро компилит, C2 позже оптимизирует горячее агрессивно
    C)Компиляция в два прохода на диске: C1 создаёт.class, а C2 превращает его в нативный образ заранее
    D)Две независимые JVM, где C1 запускает приложение, а C2 дублирует его для отказоустойчивости
    показать ответ и разбор
    +B)Многоуровневая компиляция: C1 быстро компилит, C2 позже оптимизирует горячее агрессивно

    // разбор: Tiered compilation комбинирует два JIT-компилятора: C1 (client) компилирует быстро с базовой оптимизацией и собирает профиль, а C2 (server) позже перекомпилирует САМЫЕ горячие методы с агрессивными оптимизациями (инлайнинг, устранение аллокаций и т.д.). Так достигается и быстрый прогрев (C1), и высокая пиковая производительность (C2). Уровни переключаются по счётчикам вызовов/циклов. GraalVM предлагает альтернативный C2 и AOT-компиляцию в нативный образ.

это 9 из 77

Ещё 68 вопросов по теме — в тренажёре, с движком повторения

Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.

Частые вопросы