[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-docker-kak-docker-vzaimodeystvuet-s-jvm-kakie-est-nyuansy":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":19,"progress":20,"seo":21},722,"kak-docker-vzaimodeystvuet-s-jvm-kakie-est-nyuansy",17,"docker","Docker","🐳","Как Docker взаимодействует с JVM? Какие есть нюансы?","Взаимодействие Docker с JVM — это набор нюансов, связанных с тем, как JVM определяет доступные ресурсы (память, CPU) в условиях ограничений cgroups контейнера.\n\n### 1. Осведомлённость JVM о лимитах контейнера\n\nДо Java 10 JVM не знала о cgroups и определяла доступную память и CPU по хосту, а не по контейнеру. Это приводило к OOM-kill, когда JVM пыталась использовать больше памяти, чем разрешено контейнеру.\n\nНачиная с Java 10+ (и бэкпорт в 8u191), флаг `-XX:+UseContainerSupport` включён по умолчанию, и JVM корректно определяет лимиты контейнера.\n\n### 2. Настройка памяти\n\n```dockerfile\n# Рекомендуемый подход — процент от памяти контейнера\nENTRYPOINT [\"java\", \"-XX:MaxRAMPercentage=75.0\", \"-jar\", \"app.jar\"]\n```\n\nПочему 75%, а не 100%? JVM использует память не только для heap:\n- Heap (основная память для объектов)\n- Metaspace (метаданные классов)\n- Thread stacks (стек каждого потока)\n- Direct memory (NIO буферы)\n- Code cache (JIT-скомпилированный код)\n- GC overhead\n\n### 3. Настройка CPU\n\nJVM определяет количество доступных процессоров из cgroups. Это влияет на:\n- Количество потоков GC\n- Размер пула `ForkJoinPool.commonPool()`\n- Количество потоков в `parallelStream()`\n\n```bash\n# Ограничение CPU\ndocker run --cpus=2.0 myapp\n```\n\n### 4. Graceful shutdown\n\nДля корректного завершения Spring Boot приложения важно, чтобы Java-процесс получал сигнал SIGTERM:\n\n```dockerfile\n# ПРАВИЛЬНО: exec-форма — java получает PID 1\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]\n\n# НЕПРАВИЛЬНО: shell-форма — SIGTERM получает shell, не java\nENTRYPOINT java -jar app.jar\n```\n\nВ Spring Boot включите graceful shutdown:\n\n```yaml\n# application.yml\nserver:\n  shutdown: graceful\nspring:\n  lifecycle:\n    timeout-per-shutdown-phase: 30s\n```\n\n### 5. Время запуска\n\nДля ускорения запуска в контейнере:\n- Используйте `-Djava.security.egd=file:\u002Fdev\u002F.\u002Furandom`\n- Рассмотрите CDS (Class Data Sharing) или Spring AOT\n- Используйте GraalVM Native Image для сокращения времени старта до миллисекунд\n\n> **На собеседовании:** это вопрос senior-уровня. Три ключевых нюанса: (1) UseContainerSupport — JVM должна знать о лимитах контейнера (до Java 10 не знала), (2) MaxRAMPercentage=75% — heap это не вся память JVM, (3) exec-форма ENTRYPOINT для получения SIGTERM. Знание этих деталей показывает реальный production-опыт запуска Java в Docker.","","senior",[15,16,17,18,7],"jvm","memory","performance","spring-boot",[],null,{"title":22,"description":23,"ogTitle":24,"ogDescription":25,"keywords":26,"schemaAnswer":36,"featuredSnippetReady":37},"Docker и JVM: нюансы взаимодействия — Gymterview","Нюансы JVM в Docker: UseContainerSupport, MaxRAMPercentage=75%, cgroups, настройка CPU, exec-форма ENTRYPOINT для SIGTERM, graceful shutdown Spring Boot.","Docker и JVM: память, CPU и graceful shutdown — Gymterview","Три нюанса JVM в Docker: UseContainerSupport (лимиты контейнера), MaxRAMPercentage=75% (heap не вся память), exec-форма для SIGTERM.",[27,28,29,30,31,32,33,34,35],"Docker JVM","UseContainerSupport","MaxRAMPercentage","cgroups","OOM kill Docker","graceful shutdown","PID 1","Java Docker","собеседование","Три ключевых нюанса: 1) UseContainerSupport (включён с Java 10+) — JVM определяет лимиты по cgroups контейнера, а не хоста; до Java 10 JVM не знала о лимитах и получала OOM kill. 2) MaxRAMPercentage=75% — heap это не вся память JVM (есть Metaspace, thread stacks, direct memory, code cache, GC overhead). 3) Exec-форма ENTRYPOINT — Java-процесс получает PID 1 и SIGTERM для graceful shutdown. CPU лимиты влияют на GC-потоки и ForkJoinPool.",true]