Advanced Java Backend: Модули
Программа помогает перейти от уровня junior к разработчику, который самостоятельно ведёт реальный сервис. Основной упор: как работают JVM и память, как правильно строить concurrency и работу с базой данных и как диагностировать проблемы в условиях, близких к production. Code review отрабатывается с двух сторон: как автор и как ревьюер.
01
JVM и память
Как JVM управляет кодом и памятью и как исследовать проблемы с памятью на основе измерений.
- Heap, stack, metaspace и время жизни объекта
- Сборщики мусора (G1, ZGC) и понятие пауз
- Загрузка классов и JIT-компиляция
- Чтение heap dump и GC-логов
- Типичные источники утечек (кэши, listener, ThreadLocal)
Лабораторная: Проанализировать сервис с намеренной утечкой памяти по heap dump, найти источник и исправить.
02
Concurrency и virtual threads
От Java Memory Model до virtual threads: как писать корректный и безопасный параллельный код.
- Java Memory Model, happens-before и видимость
- synchronized, Lock, atomic и concurrent-коллекции
- ExecutorService, CompletableFuture и structured concurrency
- Virtual threads: когда они полезны, проблема pinning
- Диагностика deadlock, livelock и starvation
- Чтение thread dump
Лабораторная: Создать race condition в коде, обновляющем общий счёт, воспроизвести его тестом, затем исправить двумя разными способами и сравнить.
03
JPA и Hibernate в глубину
Безопасно работать с JPA нельзя, не зная, как на деле ведут себя persistence context, flush и lazy loading.
- Persistence context, dirty checking и режимы flush
- Lazy и eager загрузка, проблема N+1
- Fetch join, entity graph и projection
- Batch insert/update и optimistic locking
- Границы транзакций и причины LazyInitializationException
Лабораторная: Измерить по SQL-логам endpoint с проблемой N+1, исправить тремя способами и сравнить число запросов.
04
SQL и производительность запросов
Как по плану понять, почему запрос медленный, и выбрать правильный индекс.
- Чтение EXPLAIN / EXPLAIN ANALYZE
- B-tree индексы, составные индексы и порядок столбцов
- Covering index и селективность
- Пагинация: offset и keyset
- Уровни изоляции и поведение блокировок
Лабораторная: Проанализировать медленный запрос на большой таблице по плану, добавить индекс и показать измерения до и после в письменной записке.
05
Стратегия тестирования
Определяем, что тестировать на каком уровне, чтобы тесты оставались дешёвыми и надёжными.
- Пирамида тестирования и её ограничения
- JUnit 5, Mockito и чрезмерное использование моков
- Integration-тесты на реальной БД с Testcontainers
- Slice-тесты (@DataJpaTest, @WebMvcTest)
- Причины flaky-тестов и как их устранять
Лабораторная: Написать документ со стратегией тестирования для существующего сервиса и добавить integration-тест на Testcontainers для критичного сценария.
06
Чистый код в растущей кодовой базе
Как управлять структурой, именованием и зависимостями, когда кодовая база растёт.
- Структура пакетов и правила зависимостей между слоями
- Отделение доменной модели от сервисного кода
- Техники рефакторинга и изменения под защитой тестов
- Проектирование исключений и модели ошибок
- Как сделать технический долг видимым
Лабораторная: Разбить сложный сервисный класс на небольшие части с чёткой ответственностью, сохраняя зелёные тесты.
07
Диагностика проблем, близких к production
Системный подход к медленной работе, росту памяти и тихим сбоям.
- Structured logging и correlation ID
- Метрики Micrometer и ключевые сигналы
- Чтение профайлеров и flame graph
- Исчерпание connection pool и насыщение thread pool
- Метод диагностики на основе гипотез
Лабораторная: Продиагностировать намеренно сломанный сервис (исчерпание пула, медленный запрос) только по логам, метрикам и профайлеру и написать postmortem.
08
Практика code review
Review — это и навык, и командная привычка; отрабатываем её с обеих сторон.
- Подготовка небольших и понятно описанных Pull Request
- Чек-лист review: корректность, читаемость, тесты, риск
- Конструктивная обратная связь и ответы на неё
- Сигналы безопасности и производительности на review
Лабораторная: Письменно проревьюить предложенный Pull Request, затем аргументированно ответить на комментарии к собственному Pull Request.