Архитектура JVM — кратко и по делу
Class Loader Subsystem
JVM загружает классы с помощью системы загрузчиков (Class Loaders), которая реализует модель делегирования:
- Bootstrap ClassLoader – загружает стандартные классы из JDK (
rt.jarили модули JDK). - Extension ClassLoader – загружает библиотеки из
extдиректории. - Application ClassLoader – загружает классы из classpath.
- Пользователь может создать Custom ClassLoader для динамической загрузки (например, в OSGi, плагинах).
Runtime Data Areas
- Heap – область, где живут все объекты.
- Method Area (Metaspace) – содержит метаинформацию классов, константный пул.
- JVM Stack – создается на поток, содержит фреймы вызовов методов.
- Program Counter Register (PC Register) — это маленький указатель, который хранит номер следующей команды, которую должен выполнить поток.
- Native Method Stack – стек для вызова нативных методов.
Execution Engine
- Interpreter – пошаговая интерпретация bytecode.
- JIT Compiler (Just-In-Time) – компилирует часто используемые методы в машинный код.
- GC Interface – Execution Engine тесно связана со сборщиком мусора: он должен знать, когда объект больше не используется, и правильно освобождать память.
Delegation Model
Delegation Model (модель делегирования ClassLoader-ов) — это механизм, с помощью которого JVM загружает классы в строгом порядке сверху вниз, чтобы избежать конфликтов и дублирования.
Когда ClassLoader хочет загрузить класс, он сначала делегирует эту задачу своему родителю, и только если родитель не нашёл класс, он загружает его сам.
Управление памятью JVM
В JVM память делится на несколько областей, и у каждой своя роль
- Heap (куча)
- Здесь хранятся экземпляры объектов.
- Для каждого объекта выделяется место под его поля (данные).
- Ссылки на объекты тоже создаются, но обычно эти ссылки хранятся в стеке или в полях других объектов на куче.
- Stack (стек)
- Здесь хранятся локальные переменные метода, включая ссылки на объекты в куче.
- Когда метод завершает выполнение, его фрейм из стека удаляется.
- Metaspace (метаспейс)
- Здесь хранятся классы и их структура: методы, константы, информация о полях.
- Не хранит сами экземпляры объектов
Heap
- Young Generation: o Eden – новые объекты. o Survivor Spaces (S0/S1) – промежуточные зоны.
- Old Generation – объекты, пережившие несколько сборок в Young Gen.
Stack
Каждый поток имеет свой собственный стек, состоящий из фреймов вызова методов. В каждом фрейме хранятся:
- локальные переменные метода,
- операндный стек для промежуточных вычислений,
- ссылка на constant pool класса, чтобы использовать константы и методы этого класса.
Metaspace
- Что хранится: информация о классах — их метаданные, методы, константы, аннотации.
- Отличие от PermGen: в Java 8+ PermGen убрали, а Metaspace хранится в нативной памяти, а не в heap. Это позволяет JVM динамически расширять пространство для метаданных без жёсткого лимита (если не задан
-XX:MaxMetaspaceSize). - Рост и лимиты: растёт по мере загрузки новых классов; можно ограничить через JVM параметры (
MaxMetaspaceSize,MetaspaceSize).
Off-heap Memory
Это память, выделяемая вне стандартного heap JVM, напрямую в нативной памяти.
- Примеры:
ByteBuffer.allocateDirect()— прямой буфер для работы с нативной памятью, минуя GC.- Пулы нативных ресурсов, кэширование больших данных.
- Опасности:
- JVM не отслеживает эту память, поэтому утечки возможны.
- Неправильное освобождение памяти (
DirectByteBuffer) может привести к OutOfMemoryError, даже если heap пустой.
Constant pool
Constant Pool — это специальное место в метаданных класса (часть Method Area в JVM), где хранятся константы, литералы и ссылки на методы/классы.
То есть constant pool — это как шкаф с готовыми вещами, а stack — это стол, на котором ты их раскладываешь для работы.
Garbage collector (CG)
GC - механизм JVM, который автоматически освобождает память, занятую объектами, на которые больше нет ссылок.
В современных JVM один Garbage Collector может использовать разные алгоритмы для разных областей памяти:
- Copying (копирующий) — применяется в Young Generation. Он быстро копирует живые объекты в новый участок памяти, а все остальное считается мусором.
- Mark-Sweep-Compact (отметь-удали-компактизируй) — чаще применяется в Old Generation. Сначала помечаются живые объекты (Mark), затем удаляются мусорные (Sweep), и оставшиеся уплотняются (Compact), чтобы избежать фрагментации.
Виды GC
Serial GC
- Использует один поток для всех фаз GC.
- Подходит для однопоточных приложений и небольших heap.
- Алгоритм: “copying” (в Young Gen) и “mark-sweep-compact” (в Old Gen).
- Параметр:
-XX:+UseSerialGC
Parallel GC (Throughput Collector)
- Использует несколько потоков для работы в Young и Old Gen.
- Цель — максимальная пропускная способность, а не минимизация пауз.
- Подходит для серверных приложений без строгих требований к задержкам.
- Параметр:
-XX:+UseParallelGC
CMS (Concurrent Mark Sweep) [устарел]
- Работает параллельно с приложением (concurrent), уменьшая stop-the-world паузы.
- Этапы: initial mark, concurrent mark, remark, sweep.
- Не компактизирует память (может привести к фрагментации).
- Устарел начиная с Java 9 и удалён в Java 14
- Параметр:
-XX:+UseConcMarkSweepGC
G1 GC (Garbage First)
- Делит heap на множество регионов.
- Каждый регион может быть частью Young или Old Generation.
- Этапы GC включают: Initial Mark, Concurrent Mark, Remark, Cleanup, Copy.
- Работает по принципу “сборка сначала самых мусорных регионов” (Garbage First).
- Использует предсказуемые паузы и старается не превышать
MaxGCPauseMillis - Поддерживает инкрементальную, concurrent и компактизирующую сборку Old Gen.
- G1 ведёт статистику “полезности” регионов и выбирает наиболее эффективные для сборки.
- Параметр:
-XX:+UseG1GC - По умолчанию используется с Java 9+
ZGC (Z Garbage Collector)
- Поддерживает heap до терабайт.
- Работает с паузами менее 10 мс, независимо от размера heap.
- Полностью concurrent (почти все фазы выполняются параллельно с приложением).
- Подходит для latency-чувствительных систем.
- Параметр:
-XX:+UseZGC
Shenandoah
- Похож на ZGC, с акцентом на короткие паузы.
- Использует concurrent compacting.
- Поддерживается OpenJDK.
- Параметр:
-XX:+UseShenandoahGC
Какой GC по умолчанию в Java
| Версия Java | GC по умолчанию |
| java 8 | Parallel GC |
| java 9+ | G1 GC |
Некоторые JDK (например, Azul Zulu) могут использовать ZGC или Shenandoah по умолчанию, если заданы специфичные цели latency
Паузы
- Stop-the-world – при некоторых фазах GC все потоки приостанавливаются.
- Minor GC – в Young Generation.
- Major/Full GC – в Old Generation, может включать очистку Metaspace.
Performance и тюнинг
-Xms/-Xmx– минимальный/максимальный размер heap.-Xss– размер стека на поток.-Xss– размер стека на поток.-XX:+PrintGCDetails,-Xlog:gc
JIT (Just-In-Time) компиляция
- JVM сначала интерпретирует байт-код, но часто выполняемые методы компилируются в нативный машинный код во время работы программы.
- Позволяет ускорить выполнение, избегая постоянной интерпретации.
- Оптимизации
- Inlining — метод “встраивается” в вызывающий код, чтобы убрать накладные расходы на вызов метода.
- Escape Analysis — анализирует, покидает ли объект метод/поток; если нет — объект может быть размещен в стеке вместо кучи, что снижает нагрузку на GC.
Class Loading и Reflectio
Delegation Model
ClassLoader сначала делегирует загрузку родителю, и лишь потом пытается загрузить сам.
Custom ClassLoaders
Нужны для:
- плагинов
- модульных систем (OSGi, Spring Boot)
- горячей перезагрузки кода
Reflection
Reflection позволяет динамически работать с классами и их членами, создавать прокси, но замедляет выполнение и может нарушать инкапсуляцию. SecurityManager может ограничивать такие операции.
Типы ссылок в java
Strong Reference (сильная ссылка)
- Это обычные ссылки, которые мы используем каждый день.
- Пока на объект существует хотя бы одна сильная ссылка — он не подлежит сборке мусора.
- Чтобы объект мог быть собран, все сильные ссылки на него должны быть обнулены.
Object obj = new Object();Soft Reference (мягкая ссылка)
- Объект удаляется только при нехватке памяти.
- Используется в кешах, чтобы не загружать память, но сохранить объект, если он ещё полезен.
- Можно получить объект через
ref.get(), но если GC уже удалил его — вернётсяnull.
SoftReference<Object> ref = new SoftReference<>(new Object());Weak Reference (слабая ссылка)
- Объект может быть собран немедленно, даже если только слабые ссылки на него остались.
- Используется для реализации структур с автоудалением (например,
WeakHashMap). - Часто применяется, когда объект должен быть доступен «до тех пор, пока он кому-то нужен».
WeakReference<Object> ref = new WeakReference<>(new Object());Phantom Reference (фантомная ссылка)
- Объект уже помечен как удаляемый, но ещё не собран GC.
- Метод
get()всегда возвращает**null**. - Используется для контроля финализации и освобождения ресурсов вне heap (например, off-heap, native).
- Требует
ReferenceQueue, через которую можно узнать, что объект вот-вот будет удалён.
PhantomReference<Object> ref = new PhantomReference<>(new Object(), referenceQueue);Итог
Сегодня мы разобрали ключевые аспекты JVM, работу памяти и сборку мусора, которые чаще всего встречаются на собеседованиях по Java. Конечно, не обязательно, что спросят всё из этого списка, но с ним вы сможете уверенно обсуждать эти темы и точно не растеряетесь.