Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
cgroups в Linux и Java приложения
cgroups (control groups) — это механизм Linux ядра для ограничения, управления и мониторинга ресурсов процессов. Это критически важно для работы контейнеризации (Docker, Kubernetes) и виртуализации.
Основной принцип
cgroups позволяют:
- Ограничить использование CPU, памяти, дискового I/O
- Приоритизировать процессы
- Отследить использование ресурсов
- Изолировать процессы
Как Java работает с cgroups
Java автоматически обнаруживает ограничения cgroups и адаптирует свое поведение:
// В Docker контейнере с ограничением памяти 512MB
// Java автоматически устанавливает -Xmx на основе лимита cgroups
public class MemoryDetection {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
// В обычном процессе возвращает физическую память компьютера
long totalMemory = runtime.totalMemory(); // Выделено JVM
long maxMemory = runtime.maxMemory(); // -Xmx
long freeMemory = runtime.freeMemory(); // Свободно в JVM
System.out.println("Max memory: " + maxMemory / (1024 * 1024) + "MB");
System.out.println("Free memory: " + freeMemory / (1024 * 1024) + "MB");
}
}
cgroups v1 vs v2
cgroups v1 (старая версия):
# Структура папок в /sys/fs/cgroup/
memory/ # Контроль памяти
cpu/ # Контроль CPU
cpuacct/ # Учет CPU
cgroups v2 (современная версия, Ubuntu 21.04+):
- Единая иерархия вместо множественной
- Лучше распределение ресурсов между процессами
Ограничение памяти в Docker
FROM openjdk:17
WORKDIR /app
COPY target/app.jar .
# Java автоматически обнаружит это ограничение через cgroups
ENTRYPOINT ["java", "-jar", "app.jar"]
# Запуск контейнера с ограничением памяти
docker run -m 512m my-java-app
// Внутри контейнера Java "видит" ограничение
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
// Скорее всего будет примерно 512MB
Ограничение CPU
# Использовать только 1 CPU ядро
docker run --cpus="1" my-java-app
# Использовать 50% всех доступных ядер
docker run --cpus="0.5" my-java-app
# Приоритет CPU
docker run --cpu-shares=512 my-java-app
// Java может получить информацию о доступных процессорах
int availableProcessors = Runtime.getRuntime().availableProcessors();
// В контейнере с --cpus="1" вернет 1
ExecutorService executor = Executors.newFixedThreadPool(availableProcessors);
Мониторинг использования ресурсов
import java.lang.management.MemoryMXBean;
import java.lang.management.ManagementFactory;
public class ResourceMonitor {
public static void main(String[] args) {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
long heapUsed = memoryBean.getHeapMemoryUsage().getUsed();
long heapMax = memoryBean.getHeapMemoryUsage().getMax();
System.out.println("Heap used: " + heapUsed / (1024 * 1024) + "MB");
System.out.println("Heap max: " + heapMax / (1024 * 1024) + "MB");
System.out.println("Heap usage: " + (100 * heapUsed / heapMax) + "%");
}
}
Важные флаги JVM для контейнеров
java -XX:+UseContainerSupport \\
-XX:MaxRAMPercentage=75.0 \\
-XX:+UnlockExperimentalVMOptions \\
-XX:G1NewSizePercent=30 \\
-XX:G1MaxNewSizePercent=40 \\
-jar app.jar
- UseContainerSupport: автоматическое обнаружение cgroups (Java 10+)
- MaxRAMPercentage: использовать 75% от лимита памяти контейнера
- G1NewSizePercent: оптимизация GC для контейнеров