Справочник по конфигурациям в Java
Назначение
Справочник-шпаргалка по конфигурациям в Java: типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс: [раздел](/encyclopedia/5-languages/5.03. Java/intro).
Краткое пояснение
Компоненты и ключевые особенности конфигураций Java.
Быстрый старт
# Полный GC-лог с ротацией
-Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=5,filesize=20M
# JIT-компиляция и инлайнинг
-Xlog:jit+compilation=info,jit+inlining=debug:file=jit.log
# Загрузка модулей и классов
-Xlog:class+load=info,modules=info:stdout
# JFR-события в реальном времени (требует JFR)
-Xlog:jfr*=trace:stdout
Справочные таблицы
Содержание справочника
- 1. JVM-аргументы запуска (
java [options] …) - 2. Системные свойства среды выполнения
- 3. Конфигурация безопасности
- 4. Логирование
- 5. Конфигурация модульной системы (JPMS)
- 6. Конфигурация сборки и развёртывания
- 7. Конфигурация инструментов JDK
- 8. Spring Boot — внешняя конфигурация
- 9. Jakarta EE / MicroProfile Config
- 10. Конфигурация сетевых и HTTP-клиентов
1. JVM-аргументы запуска (java [options] …)
Все JVM-аргументы подразделяются на три группы:
-D<property>=<value>— установка системных свойств;-X— нестандартные опции (non-standard), могут отличаться между реализациями JVM;-XX— экспериментальные и внутренние опции управления поведением JVM.
1.1. Системные свойства (-D)
Свойства, устанавливаемые при старте JVM через -Dkey=value, становятся доступны через Система.getProperty("key"). Некоторые из них влияют на поведение стандартных библиотек или JVM.
| Свойство | Описание | Возможные значения | Пример |
|---|---|---|---|
java.version | Версия Java Runtime Environment (только для чтения) | Строка, например 17.0.12 | — |
java.home | Путь к установке JRE | Абсолютный путь | /usr/lib/jvm/java-17-openjdk |
java.class.path | Путь кисходным классам и JAR-файлам | Список путей, разделённых : (Unix) или ; (Windows) | -cp lib/*:app.jar |
java.library.path | Поиск нативных библиотек (.so, .dll, .dylib) при вызове Система.loadLibrary | Список путей | -Djava.library.path=/opt/native |
java.io.tmpdir | Каталог временных файлов | Путь к директории | /tmp, C:\Temp |
file.encoding | Кодировка по умолчанию для операций ввода-вывода | UTF-8, ISO-8859-1, Windows-1251 и др. | -Dfile.encoding=UTF-8 |
sun.stdout.encoding, sun.stderr.encoding | Кодировка потоков System.out и System.err | Та же, что file.encoding, но можно задать отдельно | -Dsun.stdout.encoding=UTF-8 |
user.language, user.country, user.variant | Локаль по умолчанию | en, ru; US, RU; POSIX, WIN | -Duser.language=ru -Duser.country=RU |
user.timezone | Часовой пояс по умолчанию | UTC, Europe/Moscow, Asia/Yekaterinburg | -Duser.timezone=Europe/Moscow |
http.proxyHost, http.proxyPort, https.proxyHost, https.proxyPort | Настройка HTTP/HTTPS-прокси | Хост и порт | -Dhttp.proxyHost=proxy.local -Dhttp.proxyPort=3128 |
http.nonProxyHosts | Хосты, к которым прокси не применяется | Список имён, разделённых ` | , возможны *и?` |
socksProxyHost, socksProxyPort | SOCKS-прокси | Хост и порт | -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080 |
java.net.preferIPv4Stack | Использовать IPv4-стек при наличии дуального стека | true, false | -Djava.net.preferIPv4Stack=true |
java.net.preferIPv6Addresses | Предпочитать IPv6-адреса при разрешении имён | true, false | -Djava.net.preferIPv6Addresses=true |
networkaddress.cache.ttl | TTL кэша DNS-имён (в секундах), положительное число | 0 (никогда не кэшировать), -1 (кэшировать навсегда), 30, 60, и т.д. | -Dnetworkaddress.cache.ttl=30 |
networkaddress.cache.negative.ttl | TTL для отрицательных DNS-ответов | то же | -Dnetworkaddress.cache.negative.ttl=10 |
jdk.tls.client.protocols, jdk.tls.server.protocols | Разрешённые TLS-протоколы | TLSv1.2, TLSv1.3, TLSv1,TLSv1.1,TLSv1.2 | -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 |
jdk.tls.disabledAlgorithms | Алгоритмы, запрещённые для TLS | Список, как в java.Безопасность (см. ниже) | -Djdk.tls.disabledAlgorithms=SSLv3, RC4, MD5 |
javax.net.ssl.trustStore, javax.net.ssl.trustStorePassword, javax.net.ssl.keyStore, javax.net.ssl.keyStorePassword | Пути и пароли к хранилищам сертификатов | Путь к файлу JKS/PKCS12, пароль | -Djavax.net.ssl.trustStore=trust.jks -Djavax.net.ssl.trustStorePassword=changeit |
jdk.serialFilter | Глобальный фильтр десериализации (Java ≥ 9) | Паттерн в формате pattern;pattern;… | -Djdk.serialFilter="!*" (запрет всех), com.example.*;maxdepth=5 |
java.util.concurrent.ForkJoinPool.common.parallelism | Размер пула потоков ForkJoinPool.commonPool() | Целое число ≥ 1 | -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 |
sun.java2d.opengl | Использовать OpenGL для Java2D | true, false, True, False | -Dsun.java2d.opengl=True |
awt.useSystemAAFontSettings | Сглаживание шрифтов в AWT/Swing | on, off, gasp, lcd, lcd_hrgb, lcd_vrgb | -Dawt.useSystemAAFontSettings=lcd |
swing.aatext | Сглаживание шрифтов в Swing | true, false | -Dswing.aatext=true |
sun.java.launcher.pid | PID родительского процесса-запускателя (только чтение) | Целое число | — |
⚠️ Свойства, начинающиеся с
sun.*илиcom.sun.*, не являются частью официальной спецификации Java SE. Их поведение может меняться между реализациями (OpenJDK, Oracle JDK, Azul, IBM Semeru и др.).
1.2. Нестандартные -X параметры
Эти параметры реализованы в OpenJDK и совместимых сборках. Часть из них стабильна, часть устарела или удалена в новых версиях.
| Параметр | Описание | Значения / Примеры |
|---|---|---|
-Xms<size> | Начальный размер heap-памяти | -Xms256m, -Xms1g, -Xms4096m |
-Xmx<size> | Максимальный размер heap-памяти | -Xmx2g, -Xmx8192m |
-Xss<size> | Размер стека одного потока | -Xss512k, -Xss1m (по умолчанию: ~1 МБ на x64) |
-Xmn<size> | Размер молодого поколения (young generation) | -Xmn1g — эквивалентно -XX:NewSize=1g -XX:MaxNewSize=1g |
-Xnoclassgc | Отключение сборки мусора классов (устаревшее, игнорируется в новых версиях) | — |
-Xverify:<mode> | Проверка байткода (устарело в Java 13+) | remote, all, none — но в новых версиях всегда all или none, remote удалён |
| `-Xshare:auto | on | off` |
-Xloggc:<file> | Логирование GC в файл (устарело в Java 9+, заменено -Xlog:gc*) | -Xloggc:gc.log |
-Xprof | Встроенный профайлер (устарело в Java 14, удалено в 15) | — |
-Xdebug, -Xrunjdwp | Поддержка JDWP (устарело, заменено -agentlib:jdwp) | -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 |
-Xcomp, -Xint, -Xmixed | Режим JIT-компиляции | -Xcomp — компилировать всё сразу; -Xint — интерпретировать всё; -Xmixed — по умолчанию (гибрид) |
1.3. Экспериментальные -XX параметры
Эти параметры доступны через -XX:+OptionName, -XX:-OptionName, -XX:OptionName=value.
1.3.1. Память и GC
| Параметр | Описание | Значения / Примеры |
|---|---|---|
-XX:+UseSerialGC | Последовательный GC (однопоточный) | Подходит для малых heap и одноядерных сред |
-XX:+UseParallelGC | Parallel GC («пропускная способность») | По умолчанию в Oracle JDK ≤ 8 и в режиме -server |
-XX:+UseParallelOldGC | Включает Parallel Old для старшего поколения (актуально только если используется Parallel GC) | Включается автоматически при -XX:+UseParallelGC |
-XX:+UseConcMarkSweepGC | CMS GC (устарело в Java 9, удалено в 14) | — |
-XX:+UseG1GC | G1 GC (Garbage-First) | По умолчанию в Java 9–16 |
-XX:+UseZGC | Z Garbage Collector | Требует -XX:+UnlockExperimentalVMOptions до Java 15; начиная с Java 15 — без флага |
-XX:+UseShenandoahGC | Shenandoah GC | Обычно требует сборки OpenJDK с поддержкой Shenandoah |
-XX:MaxGCPauseMillis=<ms> | Целевая максимальная пауза GC (влияет на G1, Z, Shenandoah) | -XX:MaxGCPauseMillis=200 |
-XX:G1HeapRegionSize=<size> | Размер региона G1 | 1m, 2m, 4m, 8m, 16m, 32m (по умолчанию вычисляется) |
-XX:G1NewSizePercent=5, -XX:G1MaxNewSizePercent=60 | Мин/макс доля heap под молодое поколение в G1 | Проценты от общей heap |
-XX:InitiatingHeapOccupancyPercent=45 | Порог запуска concurrent cycle в G1 | Процент заполнения heap |
-XX:+AlwaysPreTouch | Выделение и «трогание» всей heap при старте | Уменьшает фрагментацию, увеличивает время старта |
-XX:+UseCompressedOops | Использование сжатых указателей (64-битный режим) | Включено по умолчанию при heap ≤ 32 ГБ |
-XX:ObjectAlignmentInBytes=<n> | Выравнивание объектов (только с +UseCompressedOops) | Степень двойки, ≥ 8, ≤ 256; по умолчанию 8 |
-XX:+UseLargePages | Использование huge pages (требует ОС-поддержки) | +UseLargePages + настройка vm.nr_hugepages в Linux |
1.3.2. JIT и компиляция
| Параметр | Описание |
|---|---|
-XX:+TieredCompilation | Многоуровневая компиляция (C1 + C2) — по умолчанию с Java 8 |
-XX:TieredStopAtLevel=1..4 | Уровень остановки компиляции (1 — интерпретатор + C1 без профилирования, 4 — C2) |
-XX:CompileThreshold=10000 | Кол-во вызовов метода до компиляции C1 (для -XX:-TieredCompilation) |
-XX:ReservedCodeCacheSize=240m | Макс. размер кэша скомпилированного кода |
-XX:+PrintCompilation | Вывод информации о компиляции в stderr |
-XX:+UnlockDiagnosticVMOptions | Разблокировка диагностических опций (для -XX:+PrintAssembly, -XX:+LogCompilation, и др.) |
-XX:+PrintAssembly | Дизассемблирование скомпилированного кода (требует hsdis библиотеки) |
-XX:CICompilerCount=<n> | Количество потоков JIT-компилятора |
-XX:+BackgroundCompilation | Фоновая компиляция (по умолчанию включена) |
1.3.3. Class Данные Sharing (CDS)
| Параметр | Описание |
|---|---|
-XX:SharedArchiveFile=<file> | Путь к архиву CDS (classes.jsa) |
-XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=app.jsa -Xshare:dump | Генерация кастомного архива |
-XX:ArchiveClassesAtExit=<file> | Автоматическое создание архива при завершении JVM |
1.3.4. JFR (Java Flight Recorder)
| Параметр | Описание |
|---|---|
-XX:+FlightRecorder | Включение JFR (по умолчанию включён в OpenJDK ≥ 11) |
-XX:StartFlightRecording=settings=<profile>,filename=<file.jfr>,duration=60s | Запуск записи при старте |
-XX:FlightRecorderOptions=repository=<dir>,maxsize=1g | Настройка хранилища и лимитов |
1.3.5. Отладка и диагностика
| Параметр | Описание |
|---|---|
-XX:+HeapDumpOnOutOfMemoryError | Создание heap-дампа при OutOfMemoryError |
-XX:HeapDumpPath=/path/to/dump.hprof | Путь для heap-дампа |
-XX:ErrorFile=/path/to/hs_err_pid%p.log | Лог ошибок JVM при крахе |
-XX:+PrintGC, -XX:+PrintGCDetails, -XX:+PrintGCDateStamps | Подробное логирование GC (устарело в Java 9+, заменено -Xlog:gc*) |
-XX:+PrintCommandLineFlags | Вывод всех нестандартных флагов при старте |
-XX:+TraceClassLoading, -XX:+TraceClassUnloading | Трассировка загрузки/выгрузки классов |
-XX:+UseGCLogFileRotation, -XX:NumberOfGCLogFiles=5, -XX:GCLogFileSize=10M | Ротация GC-логов (устарело, заменено -Xlog:gc*:file=gc.log:time,filecount=5,filesize=10M) |
1.4. Современное логирование GC и JVM через -Xlog (Java 9+)
Синтаксис:
-Xlog:[<selectors>][:[output][:[decorators][:output-options]]]
Селекторы (что логировать):
gc: сборка мусораgc+age=trace,gc+heap=debug,gc+metaspace=info,jit,class,safepoint,os,jfr,monitorinflation,modulesall=trace: всё на уровнеtrace
Выходы:
stdout,stderr,file=filename,file=filename%t(временная метка),file=filename%p(PID)
Декораторы:
time,utctime,uptime,timemillis,timenanos,pid,tid,level,tags
Примеры:
-Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=5,filesize=20M
-Xlog:jit+compilation=info,jit+inlining=debug:file=jit.log
-Xlog:class+load=info,modules=info:stdout
-Xlog:jfr*=trace:stdout
2. Системные свойства среды выполнения
Системные свойства — это ключ-значение пары, доступные внутри JVM через Система.getProperty(String key). Они формируются из нескольких источников и имеют иерархию приоритетов:
- Значения по умолчанию, заданные реализацией JVM (например,
os.name,java.version); - Параметры
-Dkey=value, переданные при запуске; - Программные вызовы
Система.setProperty(String key, String value)— действуют только после выполнения, не влияют на уже инициализированные подсистемы; - Переменные окружения — не становятся системными свойствами автоматически, но некоторые свойства считывают их значения при инициализации (например,
java.homeзависит отJAVA_HOME, если JVM запущена черезjavalauncher).
Системные свойства можно разделить по функциональным группам.
2.1. Свойства, описывающие среду выполнения
Эта группа фиксирована, доступна только для чтения, устанавливается JVM при старте.
| Свойство | Описание | Пример значения |
|---|---|---|
java.version | Версия Java (JRE) | 17.0.12 |
java.runtime.version | Полная версия JRE (включая сборку) | 17.0.12+7-Ubuntu-122.04 |
java.vm.version | Версия JVM (HotSpot) | 17.0.12+7-Ubuntu-122.04 |
java.vm.vendor | Поставщик JVM | Ubuntu, Eclipse Adoptium, Azul Systems, Inc. |
java.vm.name | Название JVM | OpenJDK 64-Bit Server VM |
java.vm.specification.version | Версия спецификации JVM | 17 |
java.specification.version | Версия спецификации Java SE | 17 |
java.specification.vendor | Поставщик спецификации | Oracle Corporation |
java.vendor | Поставщик реализации JRE | Eclipse Adoptium |
java.vendor.url | Ссылка на сайт поставщика | https://adoptium.net/ |
java.home | Корневой каталог JRE | /usr/lib/jvm/java-17-openjdk-amd64 |
java.class.version | Версия формата .class | 61.0 (Java 17 → 61, Java 21 → 65) |
2.2. Свойства операционной системы и аппаратуры
| Свойство | Описание | Пример значения |
|---|---|---|
os.name | Название ОС | Linux, Windows 10, Mac OS X |
os.version | Версия ОС | 5.15.0-101-generic, 10.0, 14.5 |
os.arch | Архитектура процессора | amd64, aarch64, x86, ppc64le |
sun.arch.Данные.model | Разрядность данных (32/64) | 64 |
sun.cpu.isalist | Поддерживаемые инструкции CPU (x86) | sse4.2,aes |
sun.cpu.endian | Порядок байтов | little, big |
⚠️
sun.*свойства непереносимы — их отсутствие возможно в альтернативных реализациях (например, GraalVM Native Image).
2.3. Пользователь и локаль
| Свойство | Описание | Значения | Примечание |
|---|---|---|---|
user.name | Имя текущего пользователя ОС | timur, Administrator | Берётся из системного вызова getpwuid / GetUserName |
user.home | Домашняя директория | /home/timur, C:\Users\Timur | |
user.dir | Текущая рабочая директория при запуске | /opt/app, D:\project | Меняется при Система.setProperty("user.dir", …) не влияет на File без абсолютного пути — поведение не определено |
user.language | Язык локали по умолчанию | en, ru, zh | Может отличаться от Locale.getDefault().getLanguage() после изменения локали |
user.country, user.region | Страна/регион | US, RU, CN | |
user.variant | Вариант локали | POSIX, WIN, EURO | |
file.separator | Разделитель пути | /, \ | Константа, не меняется |
path.separator | Разделитель путей в CLASSPATH | :, ; | |
line.separator | Символ(ы) конца строки | \n, \r\n |
2.4. Свойства ввода-вывода и кодировок
| Свойство | Описание | Значения по умолчанию | Примечание |
|---|---|---|---|
file.encoding | Кодировка по умолчанию для FileReader, FileWriter, PrintStream, PrintWriter без явной кодировки | UTF-8 (Java ≥ 18), ранее ANSI_X3.4-1968 (ASCII) или системная | Важно: в Java 17 и ранее это могло быть Cp1251 на Windows-локали ru_RU. С Java 18 — всегда UTF-8, если не переопределено через -Dfile.encoding=… |
sun.stdout.encoding, sun.stderr.encoding | Кодировка System.out и System.err | То же, что file.encoding, но может быть переопределено отдельно | Учитываются только при создании PrintStream внутри JVM, до первого использования System.out |
native.encoding | Кодировка ОС для нативных вызовов (например, имен файлов) | UTF-8, Cp1251, KOI8-R | Доступно с Java 17+, используется в Path.of(String) и Files при работе с не-UTF-8 именами |
sun.jnu.encoding | Кодировка для аргументов командной строки и имён файлов в JNI | То же, что native.encoding |
2.5. Свойства сети
Эти свойства влияют на поведение java.net API.
| Свойство | Описание | Типичные значения |
|---|---|---|
http.proxyHost | Хост HTTP-прокси | proxy.company.com, 192.168.1.10 |
http.proxyPort | Порт HTTP-прокси | 3128, 8080 |
https.proxyHost, https.proxyPort | То же для HTTPS | |
http.nonProxyHosts | Список хостов, к которым прокси не применяется | `localhost |
ftp.proxyHost, ftp.proxyPort | FTP-прокси | |
socksProxyHost, socksProxyPort | SOCKS-прокси (версия 5) | |
java.net.useSystemProxies | Использовать системные настройки прокси (только на Windows/macOS) | true, false |
networkaddress.cache.ttl | Время жизни кэша DNS-имён (секунды) | -1 — кэшировать вечно, 30 — 30 сек, 0 — не кэшировать |
networkaddress.cache.negative.ttl | TTL для отрицательных DNS-запросов | 10 по умолчанию |
sun.net.inetaddr.ttl | Устаревшее, эквивалентно networkaddress.cache.ttl | |
java.net.preferIPv4Stack | Использовать IPv4 при наличии дуального стека | true, false |
java.net.preferIPv6Addresses | Предпочитать IPv6-адрес при разрешении имён | true, false |
jdk.net.URLClassPath.disableNonFileURLs | Запрет загрузки классов по не-file URL | true, false |
⚠️ Прокси-настройки применяются только к
HttpURLConnection,URL.openConnection(). Клиенты вродеHttpClient(Java 11+) илиOkHttpне используют их — требуют явной конфигурацииProxySelector.
2.6. Свойства безопасности
| Свойство | Описание |
|---|---|
java.Безопасность.manager | Включение SecurityManager (устарело в Java 17, удалено в 18) |
java.Безопасность.policy | Путь к файлу политики безопасности (актуально только при наличии SecurityManager) |
java.Безопасность.auth.login.config | Файл конфигурации JAAS |
java.Безопасность.krb5.conf | Путь к krb5.conf для Kerberos |
javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, javax.net.ssl.trustStorePassword | Параметры доверенного хранилища |
javax.net.ssl.keyStore, javax.net.ssl.keyStoreType, javax.net.ssl.keyStorePassword | Параметры клиентского хранилища ключей |
javax.net.ssl.keyStoreProvider | Провайдер хранилища |
javax.net.debug | Отладка SSL/TLS соединений |
2.7. Свойства локализации и форматирования
| Свойство | Описание | Пример |
|---|---|---|
user.timezone | Часовой пояс по умолчанию | UTC, Europe/Moscow |
java.locale.providers | Порядок провайдеров локализации (Java 9+) | COMPAT,SPI,CLDR,JRE — приоритет от левого к правому |
java.util.PropertyResourceBundle.encoding | Кодировка .properties файлов | ISO-8859-1 (по умолчанию), UTF-8 (начиная с Java 9, если файл содержит  BOM или указано явно) |
🔹 Начиная с Java 9,
PropertyResourceBundleподдерживает UTF-8 без экранирования, если файл сохранён в UTF-8 с BOM или указано-Djava.util.PropertyResourceBundle.encoding=UTF-8.
2.8. Свойства параллелизма
| Свойство | Описание | Значение по умолчанию |
|---|---|---|
java.util.concurrent.ForkJoinPool.common.parallelism | Размер ForkJoinPool.commonPool() | Runtime.getRuntime().availableProcessors() - 1, минимум 1 |
java.util.concurrent.ForkJoinPool.common.exceptionHandler | Класс обработчика исключений (FQCN) | — |
java.util.concurrent.ForkJoinPool.common.threadFactory | Класс ThreadFactory (FQCN) | — |
Пример:
-Djava.util.concurrent.ForkJoinPool.common.parallelism=4
-Djava.util.concurrent.ForkJoinPool.common.threadFactory=com.example.CustomThreadFactory
2.9. Свойства GUI (AWT/Swing)
| Свойство | Описание | Примеры |
|---|---|---|
awt.toolkit | Класс AWT Toolkit | sun.awt.X11.XToolkit, sun.awt.windows.WToolkit |
swing.defaultlaf | Look-and-Feel по умолчанию | javax.swing.plaf.metal.MetalLookAndFeel, com.sun.java.swing.plaf.gtk.GTKLookAndFeel |
swing.metalTheme | Тема Metal L&F | steel, ocean |
awt.useSystemAAFontSettings | Сглаживание шрифтов | on, off, gasp, lcd, lcd_hrgb |
swing.aatext | Включение сглаживания в Swing | true, false |
sun.java2d.opengl | Использовать OpenGL для рендеринга | True, False |
sun.java2d.d3d | Использовать Direct3D (Windows) | True, False |
sun.java2d.noddraw | Отключить DirectDraw (Windows) | true, false |
🔹 Эти свойства влияют только на приложения с GUI. На серверных JVM (headless) они игнорируются.
2.10. Свойства, управляемые переменными окружения
Некоторые системные свойства инициализируются на основе переменных окружения при старте JVM:
| Переменная окружения | Влияющее свойство | Примечание |
|---|---|---|
JAVA_HOME | java.home | Только если java запущен как $JAVA_HOME/bin/java |
CLASSPATH | java.class.path | Переопределяется опцией -cp или -classpath |
TMPDIR (Unix), TEMP, TMP (Windows) | java.io.tmpdir | Приоритет: TMPDIR > TEMP > TMP |
LANG, LC_ALL, LC_CTYPE | user.language, user.country, file.encoding, sun.jnu.encoding | JVM парсит локаль из LANG=en_US.UTF-8 → user.language=en, user.country=US, file.encoding=UTF-8 |
Пример:
LANG=ru_RU.UTF-8 LC_ALL=ru_RU.UTF-8 java -jar app.jar
2.11. Динамические свойства: Система.setProperty
Метод Система.setProperty(String key, String value) изменяет значение свойства во время выполнения. Однако:
- Не все подсистемы реагируют на изменения после инициализации (например,
file.encodingигнорируется после первого созданияInputStreamReader); - Свойства безопасности (например,
java.Безопасность.policy) не перечитываются; - Изменение
user.dirне влияет на поведениеnew File("file.txt")— относительные пути разрешаются на уровне ОС при вызовеopen(), а не внутри JVM.
Рекомендуется устанавливать конфигурационные свойства до инициализации зависимых компонентов.
3. Конфигурация безопасности
Подсистема безопасности Java включает несколько взаимосвязанных компонентов:
- Java Cryptography Architecture (JCA) — криптографические сервисы;
- Java Secure Socket Extension (JSSE) — TLS/SSL;
- Java Authentication and Authorization Service (JAAS) — аутентификация и авторизация;
- Java Generic Безопасность Services (JGSS) — Kerberos, SPNEGO;
- Policy-based и Module-based ограничения доступа — управление разрешениями;
- Безопасность Manager — устаревший механизм контроля доступа (удалён в Java 18);
- Безопасность Properties — глобальные настройки через
java.Безопасность.
Все настройки управляются через:
- файл
$JAVA_HOME/conf/Безопасность/java.Безопасность(ранее$JAVA_HOME/lib/Безопасность/java.Безопасность); - файлы политики:
java.policy,java.Безопасность.policy, пользовательские.policy; - системные свойства (
-D…); - программные вызовы (
Безопасность.addProvider,Policy.setPolicy); - параметры запуска (
-Djava.Безопасность.manager,-Djava.Безопасность.policy).
3.1. Файл java.Безопасность
Расположение:
$JAVA_HOME/conf/Безопасность/java.Безопасность(Java ≥ 9)$JAVA_HOME/lib/Безопасность/java.Безопасность(Java ≤ 8)
Это основной конфигурационный файл JVM. Он содержит директивы вида key=value, комментарии (#), и поддерживает переменные (${java.home}).
3.1.1. Провайдеры криптографии (Безопасность.provider.N)
Порядок провайдеров определяет приоритет при поиске реализации алгоритмов.
Безопасность.provider.1=SUN
Безопасность.provider.2=SunRsaSign
Безопасность.provider.3=SunEC
Безопасность.provider.4=SunJSSE
Безопасность.provider.5=SunJCE
Безопасность.provider.6=SunJGSS
Безопасность.provider.7=SunSASL
Безопасность.provider.8=XMLDSig
Безопасность.provider.9=SunPCSC
Безопасность.provider.10=JDKPSS # начиная с Java 11
Наиболее важные провайдеры:
| Провайдер | Описание |
|---|---|
SUN | Реализация MessageDigest (SHA-1, SHA-256), SecureRandom, Signature (SHA1withDSA), KeyStore (JKS), Policy |
SunRsaSign | Подписи RSA: SHA256withRSA, SHA512withRSA |
SunEC | Криптография на эллиптических кривых: EC, ECDH, ECDSA, secp256r1, secp384r1 |
SunJSSE | Реализация JSSE: SSLContext, KeyManagerFactory, TrustManagerFactory |
SunJCE | Симметричные алгоритмы: AES, DES, DESede, HmacSHA256, PBE, Cipher (GCM, CBC), KeyGenerator, SecretKeyFactory |
SunJGSS | GSS-API/Kerberos v5 |
Добавление стороннего провайдера (например, Bouncy Castle):
Безопасность.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
Или программно:
Безопасность.insertProviderAt(new BouncyCastleProvider(), 1);
3.1.2. Алгоритмы, отключённые по умолчанию
| Параметр | Описание | Пример значения |
|---|---|---|
jdk.tls.disabledAlgorithms | Алгоритмы, запрещённые в TLS | SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC |
jdk.certpath.disabledAlgorithms | Алгоритмы, запрещённые при проверке сертификатов | MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024 |
jdk.jar.disabledAlgorithms | Алгоритмы, запрещённые в подписях JAR | То же, что certpath, плюс SHA1 при определённых условиях |
jdk.Безопасность.provider.preferred | Предпочтительные провайдеры для алгоритмов | SHA256withRSA:SUN, AES/GCM/NoPadding:SunJCE |
Формат значений — список условий через запятую. Поддерживает:
keySize < N,keySize > N& usage …— применение (например,& usage TLSServer)& jdkCA— если сертификат выпущен доверенным CA изcacerts
Пример:
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, RC4, DH keySize < 2048, EC keySize < 256
3.1.3. Генератор случайных чисел
| Параметр | Описание |
|---|---|
securerandom.source | Источник энтропии для SecureRandom.getInstanceStrong() |
securerandom.strongAlgorithms | Алгоритмы, считающиеся «сильными» |
🔹
new SecureRandom()без аргументов используетNativePRNG(на базе/dev/urandom) — неблокирующий.
🔹SecureRandom.getInstanceStrong()используетNativePRNGBlocking(на базе/dev/random) — может блокироваться при нехватке энтропии.
3.1.4. Хранилища сертификатов
| Параметр | Описание | Значение по умолчанию |
|---|---|---|
javax.net.ssl.trustStore | Системное хранилище доверенных сертификатов | ${java.home}/lib/Безопасность/cacerts |
javax.net.ssl.trustStoreType | Тип хранилища | JKS, PKCS12 (по умолчанию JKS) |
javax.net.ssl.trustStoreProvider | Провайдер хранилища | SUN |
javax.net.ssl.keyStore | Клиентское хранилище ключей | — |
ssl.KeyManagerFactory.algorithm | Алгоритм KeyManagerFactory | SunX509, PKIX |
ssl.TrustManagerFactory.algorithm | Алгоритм TrustManagerFactory | PKIX, SunX509 |
Файл cacerts содержит корневые сертификаты Let’s Encrypt, DigiCert, GlobalSign и др. Его можно обновить через keytool -importcert.
3.1.5. Политики безопасности
| Параметр | Описание |
|---|---|
policy.provider | Класс реализации Policy |
policy.url.1, policy.url.2, … | Список URL файлов политики |
policy.allowSystemProperty | Разрешить подстановку системных свойств в .policy |
policy.expandProperties | Разрешить ${…} в путях в .policy |
3.1.6. JAAS (аутентификация)
| Параметр | Описание |
|---|---|
login.configuration.provider | Класс загрузчика конфигурации JAAS |
java.Безопасность.auth.login.config | Путь к jaas.conf |
3.1.7. Отладка
| Свойство | Эффект |
|---|---|
-Djava.Безопасность.debug=… | Включает детальное логирование подсистемы |
| Возможные значения: | |
access | Проверки SecurityManager (устаревшее) |
certpath | Построение и проверка цепочки сертификатов |
jar | Проверка подписей JAR |
logincontext | JAAS: логин-модули, callback |
configfile | Загрузка jaas.conf |
provider | Регистрация провайдеров |
pkcs11 | Работа с PKCS#11 |
all | Всё |
Пример:
-Djava.Безопасность.debug=certpath,logincontext
3.2. Файлы политики (.policy)
Формат:
grant [CodeSource] [, Principal ...] {
Permission permission_class ["target"] [, "action"] [, signedBy "signer"];
};
3.2.1. Элементы grant
CodeSource: источник кода —codeBase "URL"+ опциональноsignedBy "alias".codeBase "file:/opt/app/"— локальные классы;codeBase "http://example.com/"— удалённые;codeBase "file:${user.home}/"— переменные разрешаются.
Principal: субъект (JAAS), напримерPrincipal com.sun.Безопасность.auth.UnixPrincipal "timur".
3.2.2. Типы разрешений (Permission)
| Класс | Описание | Пример |
|---|---|---|
java.io.FilePermission | Доступ к файловой системе | new FilePermission("/tmp/-", "read,write,delete") |
java.net.SocketPermission | Сетевые соединения | new SocketPermission("example.com:443", "connect,resolve") |
java.lang.RuntimePermission | Операции среды выполнения | new RuntimePermission("exitVM"), "getClassLoader", "setFactory", "accessClassInPackage.sun.Прочее" |
java.lang.reflect.ReflectPermission | Рефлексия | new ReflectPermission("suppressAccessChecks") |
java.Безопасность.SecurityPermission | Изменение Безопасность-подсистемы | new SecurityPermission("putProviderProperty.SunJCE") |
java.util.PropertyPermission | Чтение/запись системных свойств | new PropertyPermission("file.encoding", "read") |
java.net.NetPermission | Сетевые настройки | new NetPermission("specifyStreamHandler"), "getProxySelector" |
javax.sound.sampled.AudioPermission | Доступ к аудио | new AudioPermission("play") |
javax.Безопасность.auth.AuthPermission | JAAS-операции | new AuthPermission("createLoginContext.myContext") |
java.Безопасность.AllPermission | Полный доступ (только для доверенного кода) | new AllPermission() |
Шаблоны в FilePermission и SocketPermission:
/tmp/-—/tmpи все подкаталоги;/tmp/*— только файлы в/tmp, без подкаталогов;"*.example.com:443"— все поддомены на порту 443;"localhost:1024-"— порты ≥ 1024.
3.2.3. Пример файла политики
grant codeBase "file:/opt/app/lib/-" {
permission java.io.FilePermission "/tmp/app.log", "write";
permission java.net.SocketPermission "api.example.com:443", "connect,resolve";
permission java.util.PropertyPermission "user.timezone", "read";
permission java.lang.RuntimePermission "accessDeclaredMembers";
};
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.Безопасность.AllPermission;
};
grant Principal com.sun.Безопасность.auth.UnixPrincipal "timur" {
permission javax.Безопасность.auth.AuthPermission "doAs";
};
Загрузка:
java -Djava.Безопасность.manager -Djava.Безопасность.policy==/opt/app/app.policy MyApp
(два = означают только этот файл, один = — добавить к системным).
3.3. JAAS: jaas.conf
Формат:
AppName {
com.sun.Безопасность.auth.module.KeyStoreLoginModule required
keyStoreURL="file:/keystore.jks"
keyStorePassword="secret";
com.sun.Безопасность.auth.module.UnixLoginModule sufficient;
};
Типы модулей:
required— должен завершиться успешно, но не прерывает цепочку при ошибке;requisite— при ошибке — сразу отказ;sufficient— при успехе — цепочка завершается успешно;optional— игнорируется, если другие модули успешны.
Встроенные модули:
| Модуль | Назначение |
|---|---|
KeyStoreLoginModule | Аутентификация по ключу из JKS/PKCS12 |
UnixLoginModule | Аутентификация через PAM (Linux/macOS) |
NTLoginModule | Аутентификация в Active Directory (Windows) |
Krb5LoginModule | Аутентификация через Kerberos |
Пример Kerberos:
KafkaClient {
com.sun.Безопасность.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/etc/Безопасность/keytabs/app.keytab"
principal="app/host@REALM"
storeKey=true
useTicketCache=false;
};
3.4. JSSE: TLS/SSL-конфигурация
3.4.1. Программная настройка SSLContext
KeyStore trustStore = KeyStore.getInstance("JKS");
try (InputStream in = Files.newInputStream(Paths.get("trust.jks"))) {
trustStore.load(in, "changeit".toCharArray());
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, tmf.getTrustManagers(), null);
3.4.2. Системные свойства для JSSE
| Свойство | Описание |
|---|---|
https.protocols | Протоколы для HttpsURLConnection |
https.cipherSuites | Разрешённые шифронаборы |
jdk.tls.client.protocols | Протоколы для всех клиентских сокетов |
jdk.tls.server.protocols | Протоколы для серверных сокетов |
jdk.tls.ephemeralDHKeySize | Размер ключа DH для обмена |
jdk.tls.namedGroups | Разрешённые эллиптические кривые |
3.4.3. Отладка TLS
-Djavax.net.debug=ssl:handshake:keygen:verbose
Уровни: ssl, handshake, keygen, session, defaultctx, all.
3.5. Устаревшее: SecurityManager
- Включался через
-Djava.Безопасность.manager(Java ≤ 17); - Все проверки
checkPermission()вызывалиSecurityManager.check…(); - Удалён в Java 18: вызов
Система.setSecurityManager()выбрасываетUnsupportedOperationException; - Рекомендуемая замена: модульные ограничения (
--limit-modules,--add-exports,--add-opens),AccessController.doPrivileged(остался, но безSecurityManagerработает как no-op), проверки на уровне приложения/контейнера.
3.6. Криптографические ограничения: JCE Jurisdiction Policy Files
До Java 8 требовались отдельные US_export_policy.jar, local_policy.jar для неограниченной криптографии.
Начиная с Java 8u161 и Java 9 — неограниченные политики включены по умолчанию. Проверка:
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println(maxKeyLen); // 2147483647 → неограничено
4. Логирование
В Java логирование реализуется через иерархию фасадов и движков. Основные компоненты:
- API — интерфейсы (
Logger,Level,Handler); - Фасады — абстракции над движками (SLF4J);
- Движки — реализации (
java.util.logging, Logback, Log4j 2); - Мосты — перенаправление вызовов между движками (
jul-to-slf4j,log4j-to-slf4j); - Форматы и транспорты —
PatternLayout, JSON, GELF, syslog, Kafka, HTTP; - Контекст — MDC (Mapped Diagnostic Context), NDLC (Nested Diagnostic Logical Context).
4.1. java.util.logging (JUL)
Встроен в Java SE. Конфигурация — через $JAVA_HOME/conf/logging.properties (Java ≥ 9) или программно.
4.1.1. Иерархия логгеров
- Корневой логгер:
""(пустая строка), эквивалентенLogger.getLogger(""); - Иерархия строится по точкам:
com.example.service→ родительcom.example→com→""; - Уровень логгера наследуется от ближайшего предка с установленным уровнем.
4.1.2. Уровни (Level)
| Уровень | Числовое значение | Назначение |
|---|---|---|
OFF | Integer.MAX_VALUE | Отключение логирования |
SEVERE | 1000 | Критические ошибки (исключения, сбои) |
WARNING | 900 | Предупреждения (потенциально некорректное поведение) |
INFO | 800 | Информационные сообщения (старт, завершение, ключевые события) |
CONFIG | 700 | Конфигурационная информация (версии, параметры) |
FINE | 500 | Отладка уровня сервиса |
FINER | 400 | Подробная отладка |
FINEST | 300 | Наиболее детальная отладка |
ALL | Integer.MIN_VALUE | Всё |
Программное управление:
Logger logger = Logger.getLogger("com.example");
logger.setLevel(Level.FINE);
4.1.3. Обработчики (Handler)
| Класс | Описание |
|---|---|
ConsoleHandler | Вывод в System.err |
FileHandler | Запись в файл, поддерживает ротацию (%u, %g, %t) |
StreamHandler | Произвольный OutputStream |
SocketHandler | Отправка в TCP-сокет (устаревший, без TLS) |
MemoryHandler | Буферизация в памяти с триггером сброса |
AsyncHandler (Java 19+) | Асинхронная обработка (экспериментальный) |
Параметры FileHandler:
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 5242880 # 5 МБ
java.util.logging.FileHandler.count = 5 # 5 файлов
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append = true
4.1.4. Форматтеры (Formatter)
| Класс | Формат вывода |
|---|---|
SimpleFormatter | мар 13, 2025 10:05:30 ДП com.example.Main main WARNING: Message |
XMLFormatter | XML-структура лог-записи |
LogRecord.toString() | Сырой вывод (для отладки) |
Кастомный SimpleFormatter через шаблон (Java 7+):
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s%6$s%n
Где:
%1$t — время (LogRecord.getMillis),
%2$s — имя логгера,
%3$s — имя потока,
%4$s — уровень,
%5$s — сообщение,
%6$s — исключение (если есть),
%n — системный перевод строки.
4.1.5. Фильтры (Filter)
Интерфейс java.util.logging.Filter:
public boolean isLoggable(LogRecord record) {
return !record.getMessage().contains("password");
}
Устанавливается на логгер или хендлер:
logger.setFilter(filter);
consoleHandler.setFilter(filter);
4.1.6. Глобальная конфигурация: logging.properties
Расположение: $JAVA_HOME/conf/logging.properties
Пример:
handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
.level=INFO
java.util.logging.ConsoleHandler.level=WARNING
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
com.example.level=FINE
com.example.handlers=java.util.logging.FileHandler
com.example.useParentHandlers=false
Загрузка альтернативного файла:
-Djava.util.logging.config.file=/opt/app/logging.properties
4.2. SLF4J (Simple Logging Facade for Java)
Фасад, не реализующий логирование, а делегирующий вызовы движку.
4.2.1. API
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.trace("Detailed trace");
logger.debug("Debug info: {}", value);
logger.info("Operation started");
logger.warn("Potential issue: {}", cause);
logger.error("Failure", exception);
Методы:
trace(),debug(),info(),warn(),error()— 12 перегрузок на каждый уровень (с объектами, массивами, исключениями);- Поддержка параметризации:
{}заменяетсяString.valueOf(arg); - Поддержка
Supplier<String>(Java 8+):logger.debug(() -> computeExpensiveMessage()).
4.2.2. Привязка к движку
SLF4J выбирает движок по наличию JAR-файла META-INF/services/org/slf4j/impl/StaticLoggerBinder:
| JAR | Движок |
|---|---|
slf4j-simple-*.jar | Простая реализация (вывод в System.err, уровень INFO) |
slf4j-jdk14-*.jar | Привязка к java.util.logging |
logback-classic-*.jar | Logback (рекомендуется) |
slf4j-log4j12-*.jar | Log4j 1.2 (устарело) |
log4j-slf4j-impl-*.jar | Log4j 2 |
Только один StaticLoggerBinder должен быть в classpath — иначе ошибка инициализации.
4.2.3. Мосты
| Артефакт | Назначение |
|---|---|
jul-to-slf4j | Перенаправление JUL → SLF4J (через SLF4JBridgeHandler) |
log4j-over-slf4j | Замена Log4j 1.2 API → SLF4J |
jcl-over-slf4j | Замена Jakarta Commons Logging → SLF4J |
Активация JUL → SLF4J:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
4.3. Logback
Реализация SLF4J, разработанная тем же автором (Ceki Gülcü). Конфигурация: logback.xml, logback.groovy, logback-test.xml.
4.3.1. Структура logback.xml
<configuration scan="true" scanPeriod="30 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{40} [%X{traceId}] - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.example.service" level="DEBUG" additivity="false">
<appender-ref ref="FILE"/>
</logger>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
4.3.2. Appenders
| Класс | Описание |
|---|---|
ConsoleAppender | Вывод в System.out/System.err |
FileAppender | Запись в файл (без ротации) |
RollingFileAppender | Файл с ротацией (требует RollingPolicy) |
SMTPAppender | Отправка email при ERROR/WARN |
DBAppender | Запись в БД (таблицы logging_event, logging_event_property, logging_event_exception) |
SyslogAppender | Отправка в syslog (RFC 3164/5424) |
KafkaAppender (через logback-kafka-appender) | Отправка в Kafka |
AsyncAppender | Оборачивает другие appenders в асинхронную очередь |
4.3.3. Rolling Policies
| Класс | Критерий ротации |
|---|---|
TimeBasedRollingPolicy | По времени (%d{yyyy-MM-dd}) |
SizeBasedTriggeringPolicy | По размеру (maxFileSize) |
SizeAndTimeBasedRollingPolicy | По времени + размеру (%i — индекс внутри дня) |
FixedWindowRollingPolicy | Фиксированные окна (app.log, app.log.1, …) |
4.3.4. Encoders
| Тип | Описание |
|---|---|
PatternLayoutEncoder | Шаблонный вывод (аналог SimpleFormatter) |
JsonEncoder (через logback-json-classic) | Вывод в JSON (поля: timestamp, level, logger, message, thread, mdc) |
Пример JSON-шаблона:
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp/>
<logLevel/>
<loggerName/>
<threadName/>
<message/>
<mdc/>
<stackTrace/>
</providers>
</encoder>
4.3.5. Фильтры
| Класс | Описание |
|---|---|
ThresholdFilter | Пропускать записи ≥ уровня |
LevelFilter | Точный уровень (ACCEPT/NEUTRAL/DENY) |
EvaluatorFilter + JaninoEventEvaluator | Условия на Groovy/Janino: |
<expression>logger.contains("service") && message.contains("timeout")</expression> | |
MDCFilter | Фильтр по MDC-ключам |
4.3.6. MDC и NDLC
MDC.put("traceId", "abc123")— карта, привязанная к потоку;- В шаблоне:
%X{traceId}; NDLC.push("DB_CALL"),NDLC.pop()— стек для логической вложенности;- В шаблоне:
%x— вся цепочка через разделитель.
4.4. Log4j 2
Современный движок, несовместимый с Log4j 1.x. Конфигурация: log4j2.xml, log4j2.json, log4j2.yaml, log4j2.properties.
4.4.1. Структура log4j2.xml
<Configuration status="WARN" monitorInterval="30">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="File" fileName="app.log"
filePattern="app.%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<pattern>%d{ISO8601} [%t] %-5level %logger{40} [%X{traceId}] - %msg%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
<Async name="AsyncFile">
<AppenderRef ref="File"/>
</Async>
</Appenders>
<Loggers>
<Logger name="com.example.service" level="debug" additivity="false">
<AppenderRef ref="AsyncFile"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="AsyncFile"/>
</Root>
</Loggers>
</Configuration>
4.4.2. Особенности Log4j 2
| Фича | Описание |
|---|---|
| Async Loggers | Высокопроизводительное асинхронное логирование через Disruptor (до 10× быстрее) |
| Lookups | Динамические значения: ${env:HOME}, ${sys:user.name}, ${date:yyyy-MM}, ${docker:containerId} |
| Filters | BurstFilter, DynamicThresholdFilter, ScriptFilter (JavaScript/Groovy), StructuredDataFilter |
| Reliability | FailoverAppender, RoutingAppender (маршрутизация по условию) |
| JSON Template Layout | Готовые шаблоны: EcsLayout, GelfLayout, JsonTemplateLayout |
| JFR Integration | Автоматическая запись событий логирования в JFR-трассу |
Пример асинхронного логгера:
<AsyncLogger name="com.example" level="debug" includeLocation="true"/>
Требует com.lmax:disruptor в classpath.
4.4.3. Безопасное логирование
- Masking: через
RegexReplacementвPatternLayout:<PatternLayout><pattern>%m%n</pattern><regexReplacement regex="password=([^&]*)"replacement="password=***"/></PatternLayout> - SensitiveDataFilter (Log4j 2.17+): фильтр по регулярным выражениям для маскировки.
4.5. Сравнение движков
| Критерий | JUL | Logback | Log4j 2 |
|---|---|---|---|
| Производительность | Низкая | Средняя | Высокая (Async Loggers) |
| Гибкость конфигурации | Ограниченная | Высокая | Очень высокая |
| Асинхронность | Java 19+ (AsyncHandler) | AsyncAppender | AsyncAppender, AsyncLogger |
| JSON-поддержка | Нет | Через расширения | Встроенная (JsonTemplateLayout) |
| JMX-мониторинг | Да | Да | Да |
| JFR-интеграция | Нет | Нет | Да |
| Лицензия | GPL+CE | EPL 1.0 / LGPL 2.1 | Apache 2.0 |
4.6. Рекомендации по использованию
- Используйте SLF4J как API — обеспечивает независимость от движка.
- Выбирайте Logback или Log4j 2 — JUL не подходит для production-сред.
- Включайте MDC для трассировки запросов (traceId, spanId).
- Избегайте конкатенации строк — используйте параметризованные сообщения.
- Логируйте исключения полностью —
logger.error("msg", exception), а неlogger.error("msg: " + ex.getMessage()). - Маскируйте чувствительные данные на уровне appenders.
- Ограничьте уровень логирования в production —
INFOдля root,WARN/ERRORдля внешних библиотек. - Используйте ротацию и сжатие — предотвращает заполнение диска.
- Не логируйте в
System.out/System.errнапрямую — нарушает централизованное управление.
5. Конфигурация модульной системы (JPMS)
JPMS введён в Java 9 как механизм компоновки на уровне платформы. Основные цели:
- надёжная инкапсуляция внутренних API;
- улучшенная производительность запуска и потребления памяти;
- предсказуемая сборка и развёртывание.
Модуль описывается в файле module-info.java, компилируется в module-info.class, размещается в корне JAR или директории.
5.1. Синтаксис module-info.java
[open] module <module-name> {
requires [transitive] [static] <module>;
exports <package> [to <module>, …];
opens <package> [to <module>, …];
uses <service-interface>;
provides <service-interface> with <implementation-class>;
}
5.1.1. Объявление модуля
- Именованный модуль: имеет
module-info.java, имя совпадает с именем JAR-файла (без версии и.jar) или директории. - Unnamed module: код без
module-info.java— автоматически включает все JAR из classpath, экспортирует все пакеты, требует все модули. - Automatic module: JAR без
module-info.class, но в--module-path— получает имя поAutomatic-Module-NameизMANIFEST.MFили по имени файла (без версии и расширения).
Пример:
module com.example.app {
requires java.base;
requires transitive com.example.core;
requires static org.slf4j;
exports com.example.api;
exports com.example.internal to com.example.test;
opens com.example.config;
uses com.example.spi.DatabaseDriver;
provides com.example.spi.DatabaseDriver with com.example.postgres.PostgresDriver;
}
5.1.2. Директивы
| Директива | Описание | Примечания |
|---|---|---|
requires <module> | Зависимость от модуля | Без transitive — зависимость не наследуется |
requires transitive <module> | Транзитивная зависимость | Потребители модуля автоматически require этот модуль |
requires static <module> | Опциональная зависимость (только во время компиляции) | Во время выполнения модуль может отсутствовать |
exports <package> | Публикация пакета для чтения и рефлексии | Только public классы и члены доступны |
exports <package> to <module> | Ограниченная публикация (qualified export) | Доступ только указанному модулю |
opens <package> | Разрешение рефлексивного доступа к пакету | Для всех модулей (аналог --add-opens) |
opens <package> to <module> | Ограниченный opens | Только для указанного модуля |
open module <name> | Все пакеты открыты для рефлексии | Эквивалентно opens * |
uses <service> | Объявление использования сервиса через ServiceLoader | Не требует requires модуля, содержащего интерфейс |
provides <service> with <impl> | Регистрация реализации сервиса | Класс должен реализовывать интерфейс и иметь публичный конструктор без аргументов |
🔹
exportsне даёт доступ кprivate/package-privateчерез рефлексию — только черезopens.
🔹opensне даёт доступ кprivateчленам безsetAccessible(true).
🔹provides … withтребует, чтобы реализация находилась в том же модуле.
5.2. Параметры запуска JVM для JPMS
Все параметры начинаются с --.
| Параметр | Описание | Пример |
|---|---|---|
--module-path <path> | Поиск модулей (JAR с module-info.class или автоматических) | --module-path lib:mods |
--class-path <path> | Поиск классов в unnamed module | --class-path legacy/* |
-m <module>[/<main-class>], --module <…> | Запуск модуля | --module com.example.app/com.example.Main |
--add-modules <module>,… | Явное включение модулей (даже если не требуется) | --add-modules java.xml.bind (Java 9–10, удалён в 11) |
--add-exports <source-module>/<package>=<target-module> | Динамический exports | --add-exports java.base/sun.nio.ch=ALL-UNNAMED |
--add-opens <source-module>/<package>=<target-module> | Динамический opens | --add-opens java.base/java.lang=org.mockito |
--patch-module <module>=<path> | Замена/дополнение содержимого модуля | --patch-module java.base=hotfix/ |
--limit-modules <module>,… | Ограничение набора доступных модулей | --limit-modules java.base,java.logging |
--list-modules | Вывод списка всех наблюдаемых модулей | Только в консоли |
--describe-module <module> | Описание модуля | --describe-module java.base |
| `--illegal-access=deny | permit | warn |
5.2.1. Специальные значения для --add-exports / --add-opens
| Целевой модуль | Эффект |
|---|---|
ALL-UNNAMED | Все классы в unnamed module (classpath) |
ALL-СИСТЕМА | Все именованные системные модули |
ALL-MODULE-PATH | Все модули из --module-path |
java.*, jdk.* | Конкретный модуль |
Пример для Mockito (требует доступа к private полям):
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
5.3. Инструменты JPMS
5.3.1. jdeps — анализ зависимостей
Основное применение: выявление модульных зависимостей и непубличных API.
jdeps --module-path lib app.jar
jdeps --check MODULE_PATH --multi-release 17 app.jar
jdeps -R --generate-module-info mods app.jar
jdeps --jdk-internals app.jar
Важные флаги:
-cp,--class-path— classpath (для unnamed module);-mp,--module-path— модульный путь;--print-module-deps— список требуемых модулей (для--add-modules);--generate-open-module— генерацияopen moduleдля legacy-кода.
5.3.2. jlink — сборка минимальной среды выполнения
Генерирует кастомный runtime image с заданными модулями.
jlink \
--module-path $JAVA_HOME/jmods:mods \
--add-modules com.example.app,java.logging,java.xml \
--output myruntime \
--compress 2 \
--strip-debug \
--no-header-files \
--launcher app=com.example.app/com.example.Main
Флаги:
--compress=1(ZIP),=2(ZIP + удаление отладочной инфо);--strip-debug— удаление отладочных таблиц;--launcher name=module/class— создаётbin/nameиbin/name.bat;--bind-services— включение реализацийprovides … with;--ignore-signing-information— игнорирование подписей JAR.
Результат: myruntime/ содержит bin/java, conf/, lib/, release.
5.3.3. jmod — работа с .jmod-файлами
Формат .jmod — для поставки модулей разработчикам (не для развёртывания).
jmod create \
--class-path classes \
--main-class com.example.Main \
--module-version 1.0 \
--target-platform linux-amd64 \
app.jmod
jmod list app.jmod
jmod describe app.jmod
⚠️
.jmodнельзя использовать в--module-path— только вjlink --module-path ….
5.3.4. jimage — работа с modules-образом
Внутри $JAVA_HOME/lib/modules — единый образ всех модулей JRE.
jimage list $JAVA_HOME/lib/modules
jimage extract --dir extracted $JAVA_HOME/lib/modules java.base
jimage create --module-path mods --output custom.jimage
5.4. Динамические модули и ModuleLayer
JPMS поддерживает создание динамических слоёв модулей во время выполнения.
ModuleFinder finder = ModuleFinder.of(Paths.get("mods"));
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("com.example.app"));
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, ClassLoader.getSystemClassLoader());
// Получение ClassLoader модуля
ClassLoader appLoader = layer.findLoader("com.example.app");
Class<?> mainClass = appLoader.loadClass("com.example.Main");
Используется в:
- плагинных системах;
- изоляции загрузчиков;
- тестовых фреймворках (JUnit 5+).
5.5. DIAGNOSTICS: анализ модульной системы
5.5.1. Через JVM
java --describe-module java.base
java --list-modules
java -version --show-version
5.5.2. Через API
Module boot = Object.class.getModule(); // java.base
System.err.println(boot.getDescriptor().name());
// Все наблюдаемые модули
Layer.boot().modules().forEach(m ->
System.out.println(m.getName() + ": " + m.getPackages())
);
5.5.3. Ошибки и их интерпретация
| Ошибка | Причина | Решение |
|---|---|---|
module not found: X | Модуль X отсутствует в --module-path или не требуется явно | Добавить --add-modules X или включить в requires |
package Y is declared in module X, but module Z does not read it | Z не requires X, и X не exports Y в Z | Добавить requires X или --add-exports X/Y=Z |
unable to open Y in module X | Попытка рефлексии без opens | Добавить opens Y или --add-opens X/Y=Z |
provides Z with W, but W is not in this module | Реализация вне модуля | Перенести класс или использовать ServiceLoader.load(Z, layer) |
5.6. Совместимость с legacy-кодом
-
Classpath vs Module-path:
- Classpath → unnamed module → экспортирует всё, требует всё;
- Module-path → именованные/автоматические модули.
-
Split package:
Один пакет в нескольких модулях — запрещено.
Решение:--patch-module, объединение JAR, рефакторинг. -
Reflection на internal API:
--add-opens java.base/java.lang=ALL-UNNAMED— временное решение.
Рекомендуется миграция на публичные API. -
ServiceLoader в unnamed module:
ФайлMETA-INF/services/com.example.Spiв JAR на classpath работает безmodule-info.java.
6. Конфигурация сборки и развёртывания
Цель: формирование самодостаточных, безопасных и переносимых артефактов — от JAR до установщиков операционных систем.
6.1. MANIFEST.MF
Файл META-INF/MANIFEST.MF в JAR-архиве содержит метаданные. Кодировка — UTF-8 (начиная с Java 7), строки не длиннее 72 байт (перенос через пробел в начале строки).
6.1.1. Обязательные атрибуты
| Атрибут | Описание | Пример |
|---|---|---|
Manifest-Version | Версия спецификации манифеста | 1.0 |
Created-By | Инструмент создания | 17.0.12 (Eclipse Adoptium) |
6.1.2. Атрибуты запуска
| Атрибут | Описание | Примечание |
|---|---|---|
Main-Class | Полное имя класса с public static void main(String[]) | Должен быть в корне JAR или в Class-Path |
Start-Class | Используется Spring Boot — класс с @SpringBootApplication | Не стандартный, обрабатывается JarLauncher |
Launcher-Class | Для модульных JAR — модуль/класс | com.example.app/com.example.Main |
6.1.3. Атрибуты классов и зависимостей
| Атрибут | Описание | Пример |
|---|---|---|
Class-Path | Список JAR/директорий (относительно JAR) | lib/commons-lang3.jar lib/config/ |
Multi-Release | Поддержка multi-release JAR | true |
Automatic-Module-Name | Имя модуля для automatic module | org.slf4j |
⚠️
Class-Pathне поддерживает wildcard (*). Каждый JAR указывается явно.
6.1.4. Атрибуты версионирования и поставки
| Атрибут | Описание |
|---|---|
Implementation-Title, Implementation-Version, Implementation-Vendor | Идентификация реализации (доступны через Package.getImplementation*()) |
Specification-Title, Specification-Version, Specification-Vendor | Идентификация спецификации |
Sealed | Закрытие JAR: все классы должны быть подписаны и из одного источника |
Permissions | Уровень прав для Web Start (устарело) |
6.1.5. Подпись JAR (JAR Signing)
Для каждого пакета или файла — отдельная запись:
Name: com/example/
SHA-256-Digest: abc123...
Name: com/example/MyClass.class
SHA-256-Digest: def456...
Генерируется jarsigner на основе MANIFEST.MF и содержимого.
6.2. Multi-Release JAR (MRJAR)
Позволяет включать разные реализации классов для разных версий Java в один JAR.
Структура:
mylib.jar
├── META-INF/
│ └── MANIFEST.MF ← Multi-Release: true
├── com/example/Util.class ← Java 8+
└── META-INF/versions/
├── 9/com/example/Util.class ← Java 9+
├── 11/com/example/Util.class ← Java 11+
└── 17/com/example/Util.class ← Java 17+
Требования:
MANIFEST.MFсодержитMulti-Release: true;- Классы в
versions/N/должны иметь точно то же полное имя, что и в корне; - Нельзя переопределять пакеты — только классы;
- Поддерживается начиная с Java 9 (JVM выбирает версию ≤ текущей, наибольшую).
Сборка через jar:
jar --create --file mylib.jar \
--main-class com.example.Main \
-C classes8 . \
--release 9 -C classes9 . \
--release 11 -C classes11 . \
--release 17 -C classes17 .
Проверка:
jar --describe-module --file mylib.jar
unzip -l mylib.jar | grep versions
6.3. Sealed JAR
Запрещает загрузку классов из того же пакета, но из другого JAR или источника.
В MANIFEST.MF:
Name: com/example/internal/
Sealed: true
Эффект:
new URLClassLoader(new URL[]{other.jar}).loadClass("com.example.internal.X") → SecurityException.
Используется для защиты внутренних API.
6.4. jar — утилита управления архивами
6.4.1. Основные команды
| Команда | Описание |
|---|---|
jar --create --file app.jar -C classes . | Создание JAR из директории |
jar --update --file app.jar -C config application.properties | Добавление файла |
jar --extract --file app.jar | Распаковка |
jar --list --file app.jar | Список содержимого |
jar --describe-module --file app.jar | Анализ модульности |
jar --print-module-descriptor --file app.jar | Вывод module-info |
6.4.2. Модульные JAR
jar --create --file app.jar \
--main-class com.example.Main \
-C build/classes/module-info.class \
-C build/classes .
Требования:
module-info.classв корне;- имя JAR совпадает с именем модуля (рекомендуется).
6.5. jpackage — сборка native-установщиков
Генерирует пакеты для ОС: .deb, .rpm, .msi, .pkg, .app, app-image.
6.5.1. Режимы
| Режим | Описание |
|---|---|
--type app-image | Самодостаточная директория (без установщика) |
--type deb/rpm/msi/pkg/app-image | Установщик или образ |
6.5.2. Основные параметры
| Параметр | Описание | Пример |
|---|---|---|
--input <dir> | Директория с JAR и зависимостями | --input libs |
--main-jar <jar> | Главный JAR | --main-jar app.jar |
--main-class <class> | Класс main (если не в MANIFEST.MF) | --main-class com.example.Main |
--name <name> | Имя приложения | --name MyApp |
--app-version <ver> | Версия | --app-version 1.2.0 |
--vendor <name> | Поставщик | --vendor "Example Inc." |
--description <text> | Описание | --description "My Java App" |
--icon <file> | Иконка (.ico, .png, .icns) | --icon app.ico |
--linux-shortcut, --win-shortcut, --mac-package-identifier | ОС-специфичные опции |
6.5.3. Сценарий: сборка .deb с runtime
jlink \
--module-path $JAVA_HOME/jmods:libs \
--add-modules com.example.app,java.logging \
--output runtime \
--strip-debug \
--compress 2
mkdir -p package/{app,bin}
cp app.jar package/app/
cp -r runtime/* package/bin/
jpackage \
--type deb \
--input package/app \
--main-jar app.jar \
--runtime-image package/bin \
--name myapp \
--app-version 1.0.0 \
--vendor "Example" \
--description "My App" \
--linux-shortcut
Результат: myapp_1.0.0-1_amd64.deb, устанавливаемый через dpkg -i.
⚠️
jpackageтребует установленных системных утилит:
- Linux:
dpkg,rpmbuild;- Windows: WiX Toolset (3.11+);
- macOS:
pkgbuild,productbuild.
6.6. jlink — расширенные сценарии
6.6.1. Оптимизация образа
| Флаг | Действие |
|---|---|
--strip-debug | Удаление отладочной информации (line number tables, local variables) |
--compress=2 | Сжатие class-файлов (ZIP + stripping) |
--no-header-files | Удаление include/ (заголовки JNI) |
--no-man-pages | Удаление man-страниц |
--strip-native-commands | Удаление jcmd, jinfo, jmap и др. (остаётся только java) |
| `--endian little | big` |
| `--vm server | client |
6.6.2. Кастомизация release-файла
Файл release в корне образа содержит:
JAVA_VERSION="17.0.12"
MODULES="java.base java.logging com.example.app"
SOURCE="…"
IMPLEMENTOR="Eclipse Adoptium"
Можно дополнить через --release-info-file custom.properties.
6.7. jdeps — расширенный анализ
6.7.1. Генерация module-info.java
jdeps --generate-module-info mods app.jar
Автоматически определяет:
requires— по использованию классов;exports— поpublicклассам, используемым извне;opens— если обнаружено использование рефлексии.
6.7.2. Выявление недостающих зависимостей
jdeps --suggest-missing-deps app.jar
6.7.3. Проверка multi-release-совместимости
jdeps --multi-release 17 --class-path libs app.jar
6.8. Подпись JAR: jarsigner и keytool
6.8.1. Генерация ключей
keytool -genkeypair \
-alias mykey \
-keyalg RSA \
-keysize 4096 \
-sigalg SHA384withRSA \
-dname "CN=Timur Tagirov, O=IT Universe, C=RU" \
-validity 3650 \
-keystore keystore.jks \
-storepass changeit \
-keypass changeit
6.8.2. Подпись
jarsigner \
-keystore keystore.jks \
-storepass changeit \
-keypass changeit \
-sigalg SHA384withRSA \
-digestalg SHA-384 \
-tsa http://timestamp.digicert.com \
app.jar mykey
Флаги:
-tsa— сервер временных меток (требуется для валидности после истечения срока ключа);-verbose— детальный вывод;-certs— включить цепочку сертификатов.
6.8.3. Проверка подписи
jarsigner -verify -verbose -certs app.jar
Вывод включает:
- действительность подписи;
- цепочку сертификатов;
- наличие временной метки;
- соответствие политики (
jdk.jar.disabledAlgorithms).
6.9. Рекомендации по развёртыванию
- Используйте
jlink + jpackageдля production-дистрибутивов — уменьшает размер, исключает ненужные модули. - Подписывайте JAR, если требуется проверка целостности (например, в enterprise-средах).
- Избегайте
Class-Pathс абсолютными путями — нарушает переносимость. - Для библиотек — указывайте
Automatic-Module-NameвMANIFEST.MF, даже если нетmodule-info.java. - Multi-release JAR — только при необходимости — усложняет сборку и отладку.
- Sealed JAR — для внутренних SDK, где критична изоляция пакетов.
7. Конфигурация инструментов JDK
Инструменты JDK делятся на:
- Сборочные:
javac,javadoc,jar,jmod; - Диагностические:
jps,jstat,jmap,jstack,jinfo,jcmd; - Интерактивные:
jshell; - Профилировочные:
jfr.
Все они поставляются в $JAVA_HOME/bin/. Начиная с Java 11, отдельный JRE удалён — все инструменты входят в стандартный JDK.
7.1. javac — компилятор Java
7.1.1. Основные параметры
| Параметр | Описание | Пример |
|---|---|---|
-d <dir> | Директория вывода .class | -d build/classes |
-s <dir> | Директория вывода сгенерированных исходников (например, @Generated) | -s src/generated |
-sourcepath <path> | Поиск исходников зависимостей | -sourcepath src/main:src/lib |
-classpath <path>, -cp <path> | Classpath для разрешения ссылок | -cp lib/* |
--module-path <path>, -p <path> | Модульный путь | --module-path mods |
--module-source-path <path> | Исходники модулей (структура modA/src, modB/src) | --module-source-path 'modules/*/src' |
7.1.2. Целевая совместимость
| Параметр | Описание |
|---|---|
--release <N> | Компиляция для версии N (от 7 до текущей) |
-source <N>, -target <N> | Устаревшие (до Java 9); --release предпочтительнее — гарантирует корректные bootstrap-классы |
--enable-preview | Использование preview-фич текущей версии |
🔹
--release 11эквивалентно:
-source 11 -target 11 -bootclasspath $JAVA_HOME/jmods/java.base.jar(внутренне).
7.1.3. Предупреждения и линтинг (-Xlint)
| Флаг | Описание |
|---|---|
-Xlint:all | Все предупреждения |
-Xlint:none | Отключить все |
-Xlint:deprecation | Использование @Deprecated |
-Xlint:unchecked | Небезопасные операции с generic’ами |
-Xlint:varargs | Проблемы с T... и Object[] |
-Xlint:cast | Избыточные приведения типов |
-Xlint:fallthrough | Отсутствие break в switch |
-Xlint:finally | return в finally |
-Xlint:path | Недостижимые пути |
-Xlint:serial | Отсутствие serialVersionUID в Serializable |
-Xlint:module | Проблемы модульной системы |
-Werror | Любое предупреждение → ошибка |
Пример:
javac -Xlint:unchecked,deprecation -Werror -d bin src/*.java
7.1.4. Аннотации
| Параметр | Описание |
|---|---|
-processor <class> | Явное указание annotation processor’а |
-processorpath <path> | Classpath для процессоров |
-s <dir> | Куда писать сгенерированные исходники |
-implicit:none | Не компилировать классы, не указанные явно |
7.2. javadoc — генерация документации
7.2.1. Стандартные теги
| Тег | Контекст | Описание |
|---|---|---|
@param <name> | Метод/конструктор | Описание параметра |
@return | Метод | Возвращаемое значение |
@throws <Exception> | Метод | Исключение и условие его возникновения |
@see <ref> | Любой | Перекрёстная ссылка |
@link <ref> | Внутри описания | Инлайновая ссылка |
@since <version> | Любой | Версия, в которой появилось |
@deprecated | Любой | Устаревшее API |
@implSpec | Интерфейс/абстрактный метод | Требования к реализации |
@implNote | Любой | Замечание для реализатора |
7.2.2. Параметры генерации
| Параметр | Описание |
|---|---|
-d <dir> | Выходная директория |
-sourcepath <path> | Поиск исходников |
--module-path <path> | Модульный путь |
--module-source-path <path> | Исходники модулей |
-public, -protected, -package, -private | Уровень видимости |
-author, -version | Включать @author, @version |
-noindex | Не генерировать индекс |
-notree | Без иерархии классов |
-nohelp | Без ссылки на help |
-link <url> | Внешние javadoc (например, JDK) |
-stylesheetfile <css> | Кастомный CSS |
7.2.3. Модульные отчёты
javadoc \
--module-path mods \
--module com.example.app \
-d docs \
-author -version
Генерирует:
module-summary.html— обзор модуля;package-summary.html— по пакетам;- Поддержка
module-info.javaв навигации.
7.2.4. HTML5 и безопасность
Начиная с Java 17, javadoc генерирует только HTML5.
Поддержка --allow-script-in-comments удалена — скрипты в комментариях игнорируются.
7.3. jshell — интерактивный REPL
7.3.1. Запуск и режимы
| Команда | Эффект |
|---|---|
jshell | Интерактивный режим |
jshell script.jsh | Выполнение скрипта |
jshell --execution-timeout 30s | Таймаут выражения |
jshell -q | Тихий режим (без приветствия) |
jshell --startup DEFAULT, --startup <file> | Загрузка стартовых команд |
7.3.2. Встроенные команды (начинаются с /)
| Команда | Описание |
|---|---|
/help | Справка |
/list | Список всех введённых фрагментов |
/list <id> | Конкретный фрагмент |
/edit <id> | Редактирование в external editor (требует $JSHELLEDITOR или --editor) |
/drop <id> | Удаление фрагмента |
/save filename | Сохранение сессии |
/open filename | Загрузка сессии |
/env | Текущее окружение (classpath, modules, feedback) |
| `/set feedback verbose | concise |
/exit | Выход |
7.3.3. Особенности
- Поддержка
var,record,switchexpressions, текстовых блоков; - Автодополнение (
Tab); - История (
↑,↓); - Мультистрочные выражения (ввод до
;); - Возможность импорта пакетов:
/import java.util.*.
Пример:
jshell> /set feedback verbose
jshell> class Point { int x, y; Point(int x, int y) { this.x = x; this.y = y; } }
| created class Point
jshell> new Point(1, 2)
| $1 ==> Point@1a2b3c
| x: 1
| y: 2
7.4. jcmd — универсальная управляющая утилита
Выполняет команды в работающей JVM. Единственный инструмент, поддерживающий все диагностические операции в новых версиях Java (остальные (jstack, jmap) — устаревшие, реализованы через jcmd).
7.4.1. Общая структура
jcmd [<pid>|<main-class>|0] <command> [arguments]
0 — все локальные JVM.
7.4.2. Основные команды
| Команда | Описание |
|---|---|
VM.version | Версия JVM |
VM.command_line | Аргументы запуска |
VM.flags [-all] | Все флаги JVM |
VM.set_flag <name> <value> | Изменение non-manageable флага (только если manageable = true) |
GC.run | Принудительный GC (эквивалент Система.gc()) |
GC.run_finalization | Запуск finalization |
Thread.print [-l] | Стеки потоков (аналог jstack) |
VM.class_hierarchy [-i] [-v] | Иерархия классов (требует UnlockDiagnosticVMOptions) |
VM.classloader_stats | Статистика загрузчиков |
VM.stringtable [-verbose] | Интроспекция string pool |
VM.symboltable | Таблица символов |
PerfCounter.print | Счётчики производительности |
JFR.start [settings=…] [filename=…] [duration=…] | Запуск Flight Recorder |
JFR.stop [name=…] [filename=…] | Остановка и сохранение |
JFR.check | Состояние записей |
ManagementAgent.start [port=…] | Включение JMX (если не был включён при старте) |
7.4.3. Примеры
jcmd -l
jcmd 12345 Thread.print
jcmd 12345 JFR.start name=MyRecording settings=profile duration=60s filename=rec.jfr
jcmd 12345 VM.set_flag MaxGCPauseMillis 200
✅
jcmd— предпочтительный инструмент для production-диагностики.
7.5. jps — список Java-процессов
| Флаг | Описание |
|---|---|
jps | PID + короткое имя main-class/JAR |
jps -l | Полный путь к main-class или JAR |
jps -v | Аргументы JVM |
jps -m | Аргументы main-метода |
jps -q | Только PID |
Пример:
$ jps -lv
12345 /opt/app/app.jar -Xmx2g -Dfile.encoding=UTF-8
12346 org.apache.catalina.startup.Bootstrap start
7.6. jstat — статистика GC и JIT
| Команда | Описание |
|---|---|
jstat -gc <pid> [interval] [count] | Сборка мусора (Eden, Survivor, Old, Metaspace) |
jstat -gccapacity <pid> | Ёмкости поколений |
jstat -gcutil <pid> | % использования поколений |
jstat -compiler <pid> | Статистика JIT (методы, время компиляции) |
jstat -printcompilation <pid> | Последние скомпилированные методы |
Пример:
jstat -gcutil 12345 1s 5
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 98.45 76.32 45.12 95.34 92.11 123 2.345 5 1.234 3.579
Где:
S0/S1 — Survivor 0/1,
E — Eden,
O — Old,
M — Metaspace,
CCS — Compressed Class Space,
YGC/YGCT — Young GC count/time,
FGC/FGCT — Full GC count/time,
GCT — Total GC time.
7.7. jmap — анализ памяти
| Команда | Описание |
|---|---|
jmap -heap <pid> | Сводка по heap (поколения, GC, capacity) |
jmap -histo <pid> | Гистограмма классов (экземпляры, байты) |
jmap -histo:live <pid> | Только живые объекты (запускает GC) |
jmap -dump:live,format=b,file=heap.hprof <pid> | Heap-дамп в HPROF-формате |
⚠️
jmapприостанавливает JVM на время операции. В production используйтеjcmd <pid> GC.run_finalization+jcmd <pid> VM.class_histogram, или JFR.
7.8. jstack — дамп стеков потоков
| Команда | Описание |
|---|---|
jstack <pid> | Стеки всех потоков |
jstack -l <pid> | + информация о мониторах и owns |
jstack -F <pid> | Принудительный дамп (если JVM не отвечает) |
Формат вывода:
"main" #1 prio=5 os_prio=0 cpu=123.45ms elapsed=10.00s tid=0x00007f0000000000 nid=0x1234 runnable
java.lang.Thread.State: RUNNABLE
at java.util.HashMap.hash(HashMap.java:339)
at java.util.HashMap.put(HashMap.java:612)
at com.example.Main.main(Main.java:10)
🔹 В Java 8–16
jstackработает напрямую; в Java 17+ — обёртка надjcmd <pid> Thread.print.
7.9. jinfo — конфигурация JVM
| Команда | Описание |
|---|---|
jinfo <pid> | Все системные свойства и флаги |
jinfo -sysprops <pid> | Только Система.getProperty |
jinfo -flags <pid> | Только -XX флаги |
jinfo -flag <name> <pid> | Значение конкретного флага |
jinfo -flag +<name> <pid> | Включить boolean-флаг (если manageable) |
⚠️ Большинство флагов — non-manageable и не могут быть изменены в runtime.
7.10. jfr — работа с Flight Recorder
| Команда | Описание |
|---|---|
jfr status <pid> | Активные записи |
jfr start <pid> [name=…] [settings=…] [duration=…] [filename=…] | Запуск записи |
jfr stop <pid> [name=…] [filename=…] | Остановка и сохранение |
jfr dump <pid> [name=…] [filename=…] | Дамп текущего буфера без остановки |
jfr print <file.jfr> | Текстовый вывод событий |
jfr metadata <file.jfr> | Описание типов событий |
jfr extract <file.jfr> --events <type> | Извлечение подмножества событий |
Форматы settings:
default— минимальная нагрузка;profile— полная (методы, allocation, TLAB, monitor, socket);flightrecorder— кастомный (.jfc-файл).
Пример кастомного .jfc:
<configuration version="2.0">
<event name="jdk.CPULoad">
<setting name="enabled">true</setting>
<setting name="period">1 s</setting>
</event>
</configuration>
Загрузка:
jfr start 12345 settings=cpu.jfc filename=cpu.jfr
8. Spring Boot — внешняя конфигурация
Spring Boot предоставляет унифицированную модель загрузки конфигурации из множества источников, с приоритезацией, профилированием, типобезопасным связыванием и поддержкой внешних систем.
Все конфигурационные свойства доступны через Environment и @ConfigurationProperties.
8.1. Иерархия источников конфигурации
Spring Boot загружает свойства в строго определённом порядке, где более поздние источники переопределяют более ранние:
| Приоритет | Источник | Описание |
|---|---|---|
| 1 | @TestPropertySource | Аннотация на тестах |
| 2 | Аргументы @SpringBootTest(properties = …) | В тестах |
| 3 | properties атрибут @SpringBootTest, @WebMvcTest и др. | |
| 4 | Аргументы командной строки (--name=value) | Через SpringApplication.run(args) |
| 5 | Свойства из SPRING_APPLICATION_JSON (переменная окружения или системное свойство) | {"app.port":8081} → app.port=8081 |
| 6 | ServletConfig init-параметры | В веб-приложениях |
| 7 | ServletContext init-параметры | |
| 8 | JNDI-атрибуты (java:comp/env/) | |
| 9 | Система.getProperties() | Системные свойства JVM (-D…) |
| 10 | Системные переменные окружения | APP_PORT=8081 |
| 11 | RandomValuePropertySource | random.int, random.uuid |
| 12 | Профильные application-{profile}.properties из упакованного JAR | |
| 13 | application.properties из упакованного JAR (classpath:/) | |
| 14 | Профильные application-{profile}.properties из config/ в текущей директории | ./config/application-prod.properties |
| 15 | application.properties из config/ в текущей директории | ./config/application.properties |
| 16 | Профильные application-{profile}.properties в текущей директории | ./application-prod.properties |
| 17 | application.properties в текущей директории | ./application.properties |
| 18 | @PropertySource на @Configuration-классах | Загружается до application.properties, но после системных источников 1–11 — важное исключение из порядка |
| 19 | Конфиги, загруженные через spring.config.import | Выполняются в порядке объявления, после application.properties, но до @PropertySource с @DependsOn |
✅ Актуально для Spring Boot 2.4+. До 2.4 порядок
@PropertySourceбыл выше.
8.2. Синтаксис application.properties и application.yml
8.2.1. application.properties
server.port=8080
app.name=MyApp
app.version=1.2.0
app.features=auth,logging,metrics
app.ports=8080,8081,8082
app.datasource.url=jdbc:postgresql://localhost:5432/mydb
app.datasource.username=admin
app.datasource.password=secret
app.datasource.pool.size=10
app.datasource.pool.timeout=30s
app.id=${random.uuid}
app.port=${random.int[8000,9000]}
8.2.2. application.yml
server:
port: 8080
app:
name: MyApp
version: 1.2.0
features:
- auth
- logging
- metrics
ports:
- 8080
- 8081
- 8082
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
password: secret
pool:
size: 10
timeout: 30s
id: ${random.uuid}
port: ${random.int[8000,9000]}
🔹 Spring Boot использует SnakeYAML для парсинга.
🔹 Поддерживаются!!int,!!binary, но не рекомендуются — снижают переносимость.
8.3. Профили (spring.profiles.active)
8.3.1. Активация
| Способ | Пример |
|---|---|
| Системное свойство | -Dspring.profiles.active=prod,metrics |
| Переменная окружения | SPRING_PROFILES_ACTIVE=prod,metrics |
application.properties | spring.profiles.active=dev |
application.yml | spring: profiles: active: dev |
| Программно | SpringApplication.setAdditionalProfiles("test") |
8.3.2. Условная загрузка
spring:
config:
activate:
on-profile: dev
logging:
level:
com.example: DEBUG
---
spring:
config:
activate:
on-profile: prod
logging:
level:
com.example: WARN
server:
shutdown: graceful
🔹
---— разделитель документов в YAML.
🔹 Вproperties— отдельные файлы:application-dev.properties,application-prod.properties.
8.3.3. Включение профилей из кода
@Profile("integration-test")
@Configuration
public class TestDataSourceConfig { … }
8.4. spring.config.import — импорт внешних конфигураций
Введён в Spring Boot 2.4 для замены spring.config.location (устаревшего). Поддерживает:
| Префикс | Источник | Пример |
|---|---|---|
optional:classpath: | JAR/classpath (необязательный) | optional:classpath:config/external.properties |
classpath: | JAR/classpath (обязательный) | classpath:secrets.properties |
optional:file: | Файл (необязательный) | optional:file:/etc/app/config.properties |
file: | Файл (обязательный) | file:./local.conf |
configtree: | Дерево файлов как свойства | configtree:/etc/secrets/ |
vault: | HashiCorp Vault (через Spring Cloud) | vault://secret/Данные/myapp |
consul: | Consul KV (Spring Cloud) | consul:myapp/config |
zookeeper: | ZooKeeper (Spring Cloud) | zookeeper:/config/myapp |
8.4.1. configtree — безопасное хранение секретов
Структура:
/etc/secrets/
├── db.username
├── db.password
└── api.token
Содержимое файлов — plain text:
admin
В application.properties:
spring.config.import=optional:configtree:/etc/secrets/
Результат:
db.username=admin, db.password=secret, api.token=abc123.
Преимущества:
- файлы могут иметь
chmod 600; - не попадают в логи при
--debug; - не требуют шифрования внутри.
8.5. @ConfigurationProperties — типобезопасная конфигурация
8.5.1. Объявление
@ConfigurationProperties(prefix = "app.datasource")
@ConstructorBinding // immutable, требует @EnableConfigurationProperties или @ConfigurationPropertiesScan
public record DataSourceProperties(
String url,
String username,
String password,
Pool pool
) {}
public record Pool(int size, Duration timeout) {}
8.5.2. Активация
@SpringBootApplication
@EnableConfigurationProperties(DataSourceProperties.class)
public class Application { … }
Или глобально:
@ConfigurationPropertiesScan("com.example.config")
public class Config { … }
8.5.3. Валидация
@ConfigurationProperties(prefix = "app.datasource")
@Validated
public record DataSourceProperties(
@NotBlank String url,
@NotBlank String username,
@NotBlank String password,
@Valid Pool pool
) {}
public record Pool(
@Min(1) @Max(100) int size,
@NotNull @Positive Duration timeout
) {}
Ошибка приведёт к BindValidationException при старте.
8.5.4. Конвертация типов
Поддерживаются:
Duration←"30s","5m",PT30S;DataSize←"10MB","2GiB";Charset←"UTF-8";Resource←"classpath:app.sql","file:/tmp/Данные.txt";List<T>,Set<T>,Map<String, T>;- Кастомные
Converter<T, R>и@ConfigurationPropertiesBinding.
Пример конвертера:
@Component
@ConfigurationPropertiesBinding
public class PasswordConverter implements Converter<String, EncryptedPassword> {
public EncryptedPassword convert(String source) {
return new EncryptedPassword(AES.encrypt(source, key));
}
}
8.6. @Value vs @ConfigurationProperties
| Критерий | @Value | @ConfigurationProperties |
|---|---|---|
| Типизация | Строгая привязка к типу, но без вложенных объектов | Полная поддержка вложенных структур |
| Валидация | Только через SpEL (#{…}), без @Valid | Поддержка Bean Validation |
| Метаданные | Нет | Генерирует META-INF/spring-configuration-metadata.json для IDE |
| Производительность | Разбор SpEL при каждом доступе | Однократное связывание при старте |
| Иммутабельность | Только через final + конструктор | Поддержка @ConstructorBinding и record’ов |
| Тестирование | Требует @TestPropertySource | Легко заменяется моком |
Рекомендация:
— @ConfigurationProperties — для групп связанных свойств (DAO, клиенты, настройки модуля);
— @Value — для единичных значений (@Value("${app.id}") String id).
8.7. Интеграция с внешними системами
8.7.1. Spring Cloud Config Server
bootstrap.yml (загружается до application.*):
spring:
application:
name: myapp
cloud:
config:
uri: http://config-server:8888
username: client
password: secret
fail-fast: true
Конфиг на сервере: myapp-prod.yml:
app:
datasource:
url: jdbc:postgresql://prod-db:5432/mydb
8.7.2. HashiCorp Vault
spring.config.import=vault://secret/Данные/myapp
spring.cloud.vault:
host: vault.example.com
port: 8200
scheme: https
authentication: TOKEN
token: s.xxxxx
Данные из secret/Данные/myapp → app.*.
8.7.3. AWS Secrets Manager
Через spring.config.import=configtree:/mnt/secrets/, где /mnt/secrets/ — volume с секретами, примонтированными как файлы (ECS/EKS sidecar-паттерн).
8.8. Расширение конфигурационного конвейера
8.8.1. EnvironmentPostProcessor
Выполняется до обработки application.properties.
public class CustomEnvPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
Map<String, Object> map = new HashMap<>();
map.put("app.runtime", "kubernetes");
env.getPropertySources().addFirst(new MapPropertySource("custom", map));
}
}
Регистрация в META-INF/spring.factories:
org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.CustomEnvPostProcessor
8.8.2. ConfigDataLocationResolver + ConfigDataLoader
Для кастомных префиксов (например, myconf:).
-
Реализация
ConfigDataLocationResolver<MyConfigDataResource>:@Order(HIGHEST_PRECEDENCE)public class MyConfigLocationResolver implements ConfigDataLocationResolver<MyConfigDataResource> {@Overridepublic boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) {return location.hasPrefix("myconf:");}@Overridepublic List<MyConfigDataResource> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location) {return List.of(new MyConfigDataResource(location.getNonPrefixedValue()));}} -
Реализация
ConfigDataLoader<MyConfigDataResource>:public class MyConfigDataLoader implements ConfigDataLoader<MyConfigDataResource> {@Overridepublic ConfigData load(ConfigDataLoaderContext context, MyConfigDataResource resource) {Map<String, Object> props = fetchFromCustomSource(resource.getLocation());return new ConfigData(PropertySource.of("myconf", props));}} -
Регистрация в
spring.factories:org.springframework.boot.context.config.ConfigDataLocationResolver=\com.example.MyConfigLocationResolverorg.springframework.boot.context.config.ConfigDataLoader=\com.example.MyConfigDataLoader
8.9. Безопасность конфигурации
8.9.1. Шифрование значений
Jasypt (неофициально, сторонняя библиотека):
app.datasource.password=ENC(G5xJ5s1W3QzK8c9Y1U4aB2vC4nM6lO0p)
Spring Cloud Vault / AWS KMS / Azure Key Vault — предпочтительные production-решения.
8.9.2. Защита от утечек
- Запрет логирования
@ConfigurationPropertiesс@Sensitive(кастомная аннотация +PropertySourcesDeducer); - Использование
configtreeвместоapplication.propertiesдля секретов; spring.main.lazy-initialization=true— уменьшает риск преждевременного связывания.
9. Jakarta EE / MicroProfile Config
MicroProfile Config — стандарт конфигурации для микросервисов, часть спецификации MicroProfile. Принят в Jakarta EE как основа для jakarta.config (предварительно — MP Config 3.0+).
Реализации: SmallRye Config (Quarkus, WildFly), Helidon Config, Open Liberty, Payara Micro.
9.1. Основные принципы
- Декларативность: конфигурация через
@ConfigProperty,@Inject Config; - Иерархия источников: от высокоуровневых (переменные окружения) к низкоуровневым (файлы);
- Типобезопасность: автоматическая конвертация в
int,Duration,List,Map; - Динамичность: поддержка обновления конфигурации без перезапуска (в реализациях);
- Расширяемость: кастомные
ConfigSource,Converter.
9.2. Источники конфигурации и приоритеты
Приоритет определяется целым числом (ordinal). Чем больше ordinal — тем выше приоритет.
| Источник | ordinal по умолчанию | Описание |
|---|---|---|
Programmatically added ConfigSource | Указывается явно | Наивысший приоритет при ordinal > 1000 |
Система properties (-Dkey=value) | 400 | Система.getProperty() |
| Environment variables | 300 | System.getenv() |
.env файл в корне проекта | 295 | Поддерживается SmallRye, Helidon |
microprofile-config.properties в рабочей директории | 250 | ./microprofile-config.properties |
META-INF/microprofile-config.properties в JAR | 100 | Упакованный в артефакт |
Custom ConfigSource без ordinal | 100 | По умолчанию |
🔹 Переменные окружения транслируются в свойства по правилу:
APP_DATASOURCE_URL→app.datasource.url(регистронезависимо,_→.,__→_).
Пример:
export APP_DATASOURCE__URL=jdbc:postgresql://prod:5432/mydb
9.3. Формат microprofile-config.properties
Расположение:
META-INF/microprofile-config.properties— в JAR;microprofile-config.properties— в текущей директории (для dev-сред).
Синтаксис:
app.name=MyService
app.version=1.2.0
app.ports=8080,8081,8082
app.features=auth;logging;metrics # разделитель можно задать через Config API
app.timeout=30s
app.delay=5m
app.cache.size=100MB
app.datasource.password=secret
Поддерживаются те же типы, что и в Spring Boot: String, int/Integer, long/Long, boolean/Boolean, Duration, LocalDateTime, URL, URI, Charset, Class, List<T>, Set<T>, Map<String, T>.
9.4. Программное API: Config, ConfigProvider
9.4.1. Получение Config
Config config = ConfigProvider.getConfig();
// или через CDI
@Inject
Config config;
9.4.2. Чтение значений
// Обязательное значение
String name = config.getValue("app.name", String.class);
// Опциональное значение
Optional<Integer> port = config.getOptionalValue("app.port", Integer.class);
// Со значениями по умолчанию
int timeout = config.getValue("app.timeout", int.class, () -> 30);
// Списки
List<Integer> ports = config.getValues("app.ports", Integer.class);
// Map (ключ=значение, по строковому шаблону)
Map<String, String> props = config.getValues("app.datasource", String.class, String.class);
// → app.datasource.url, app.datasource.username → {url=..., username=...}
9.4.3. Интроспекция источников
config.getConfigSources().forEach(source -> {
System.out.println(source.getName() + " (ordinal=" + source.getOrdinal() + ")");
});
9.5. CDI-инъекция: @ConfigProperty
9.5.1. Базовое использование
@ApplicationScoped
public class Service {
@Inject
@ConfigProperty(name = "app.name")
String appName;
@Inject
@ConfigProperty(name = "app.ports")
List<Integer> ports;
@Inject
@ConfigProperty(name = "app.enabled", defaultValue = "true")
boolean enabled;
@Inject
@ConfigProperty(name = "app.timeout")
Duration timeout; // "30s" → Duration.ofSeconds(30)
}
9.5.2. Обработка отсутствующих значений
- Без
defaultValue—DeploymentExceptionпри старте, если свойство не найдено; - С
defaultValue— используется значение по умолчанию; Optional<T>— безопасное чтение:@Inject@ConfigProperty(name = "app.optional.token")Optional<String> token;
🔹
@ConfigPropertyработает только в CDI-биньках (@ApplicationScoped,@RequestScopedи др.).
9.6. Типобезопасная конфигурация: @ConfigProperties (MicroProfile 3.0+)
Аналог @ConfigurationProperties в Spring Boot.
9.6.1. Объявление
@ConfigProperties(prefix = "app.datasource")
public interface DataSourceConfig {
String url();
String username();
String password();
PoolConfig pool();
@ConfigProperties(prefix = "pool")
interface PoolConfig {
int size();
Duration timeout();
}
}
Или классом:
@ConfigProperties(prefix = "app.datasource")
public class DataSourceConfig {
private String url;
private String username;
private String password;
private PoolConfig pool;
// геттеры/сеттеры или record-конструктор
}
9.6.2. Инъекция
@Inject
DataSourceConfig config;
// Использование
DataSource ds = new DataSource(config.url(), config.username(), config.password());
🔹 В SmallRye Config поддерживается
@ConfigMapping(альтернативное имя для@ConfigProperties).
🔹 В Quarkus —@ConfigMappingс поддержкой@WithDefault,@WithParentName,@WithName.
9.7. Расширение: кастомные ConfigSource
9.7.1. Реализация
public class DatabaseConfigSource implements ConfigSource {
private final Map<String, String> properties = loadFromDatabase();
@Override
public int getOrdinal() {
return 500; // выше Система props
}
@Override
public Set<String> getPropertyNames() {
return properties.keySet();
}
@Override
public String getValue(String propertyName) {
return properties.get(propertyName);
}
@Override
public String getName() {
return "DatabaseConfigSource";
}
}
9.7.2. Регистрация
Через META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource:
com.example.DatabaseConfigSource
Или программно:
Config config = ConfigProviderResolver.instance()
.getBuilder()
.withSources(new DatabaseConfigSource())
.build();
ConfigProviderResolver.instance().registerConfig(config, getClass().getClassLoader());
⚠️ При программной регистрации — только для текущего
ClassLoader.
9.8. Кастомные Converter
9.8.1. Реализация
@Priority(100) // выше встроенных
public class PasswordConverter implements Converter<String> {
@Override
public String convert(String value) {
return AES.decrypt(value, getKey());
}
}
9.8.2. Регистрация
Через META-INF/services/org.eclipse.microprofile.config.spi.Converter:
com.example.PasswordConverter
Или для конкретного типа:
public class DurationConverter implements Converter<Duration> {
@Override
public Duration convert(String value) {
return Duration.parse("PT" + value.toUpperCase());
}
}
→ применяется при config.getValue("key", Duration.class).
9.9. Динамическая конфигурация и события
9.9.1. Поддержка в runtime’ах
- Quarkus:
@ConfigProperty(reactive = true)+@Observes ConfigValueChangeEvent; - SmallRye Config:
@Inject @ConfigProperty ConfigValue+ConfigValueObserver; - Helidon:
Config.onChange(…).
9.9.2. Пример (SmallRye)
@ApplicationScoped
public class ConfigObserver {
@Inject
@ConfigProperty(name = "app.feature.toggle")
ConfigValue toggle;
void onConfigChange(@Observes ConfigValueChangeEvent event) {
if ("app.feature.toggle".equals(event.getKey())) {
System.out.println("Feature toggle changed to: " + event.getValue());
}
}
}
🔹 Требует
mp.configвpom.xmlи активной поддержки в runtime.
9.10. Интеграции с runtime’ами
| Runtime | Поддержка | Особенности |
|---|---|---|
| Quarkus | Полная (SmallRye Config) | application.properties, @ConfigMapping, dev-services, config hot reload в dev mode |
| Helidon | Встроенная | application.yaml, config profiles, programmatic builder |
| Open Liberty | MP Config 3.0+ | server.xml + microprofile-config.properties, dynamic updates |
| WildFly | SmallRye Config | standalone.xml + META-INF/microprofile-config.properties |
| Payara Micro | MP Config | Поддержка configsource в payara-micro.properties |
9.10.1. Quarkus: расширенные возможности
- Profile-specific properties:
%prod.app.url=…; - Config profiles:
-Dquarkus.profile=prod; - Secrets via Kubernetes ConfigMap/Secret: автоматическое монтирование как
configmap:/иsecret:/; - Config encryption: через
smallrye-configи внешние провайдеры (Vault, KMS).
Пример application.properties в Quarkus:
%dev.app.url=http://localhost:8080
%prod.app.url=https://api.example.com
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=${db.user}
quarkus.datasource.password=${db.password}
Переменные db.user, db.password могут поступать из Kubernetes Secret.
9.11. Сравнение с Spring Boot Config
| Критерий | MicroProfile Config | Spring Boot Config |
|---|---|---|
| Стандартизация | Jakarta EE / MicroProfile | Proprietary (Pivotal/VMware) |
| Иерархия источников | ordinal-приоритет | Жёсткий порядок (17+ уровней) |
| Типобезопасность | @ConfigProperties (MP 3.0+) | @ConfigurationProperties (с 1.0) |
| Динамическая перезагрузка | Опционально (runtime-зависимо) | Через Spring Cloud Config + @RefreshScope |
| CDI-интеграция | Встроенная | Требует Spring Context |
| Профили | %profile.key=value | application-{profile}.properties |
| Конвертация | Встроенная + Converter | Встроенная + Converter/Formatter |
✅ MicroProfile Config легче встраивается в non-Spring среды (Quarkus, Helidon, Open Liberty).
✅ Spring Boot Config богаче в enterprise-интеграциях (Vault, Consul, AWS и др. «из коробки»).
10. Конфигурация сетевых и HTTP-клиентов
Java предоставляет два поколения HTTP-клиентов:
- Legacy:
java.net.URL,URLConnection,HttpURLConnection(Java 1.0+); - Modern:
java.net.http.HttpClient(Java 11+, incubated в 9–10).
Оба поддерживают HTTPS, прокси, аутентификацию, кастомные заголовки. Современный клиент добавляет HTTP/2, reactive streams, строгую типизацию.
10.1. java.net.http.HttpClient (Java 11+)
10.1.1. Создание клиента
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.followRedirects(HttpClient.Redirect.NORMAL) // NEVER, ALWAYS
.version(HttpClient.Version.HTTP_2) // HTTP_1_1, HTTP_2
.sslContext(sslContext) // кастомный SSLContext
.sslParameters(sslParameters) // кастомные параметры TLS
.executor(executor) // кастомный Executor (по умолчанию ForkJoinPool.commonPool())
.cookieHandler(cookieManager) // управление cookie
.authenticator(authenticator) // HTTP-аутентификация
.proxy(proxySelector) // выбор прокси
.build();
10.1.2. connectTimeout
- Применяется к
connect()сокета; - Не влияет на
readTimeout(устанавливается вHttpRequest.Builder); - Значение
Duration.ZERO— отключает таймаут.
10.1.3. followRedirects
| Значение | Поведение |
|---|---|
HttpClient.Redirect.NEVER | Не следовать за редиректами (3xx) |
HttpClient.Redirect.NORMAL | Следовать за GET/HEAD, не за POST/PUT/DELETE (стандарт RFC 7231) |
HttpClient.Redirect.ALWAYS | Следовать за всеми (опасно для неидемпотентных методов) |
10.1.4. Версии HTTP
| Версия | Поддержка |
|---|---|
HTTP_1_1 | Всегда доступна |
HTTP_2 | Доступна только при HTTPS и поддержке ALPN на стороне сервера |
Авто (null) | Попытка HTTP/2 → откат на HTTP/1.1 |
🔹 HTTP/2 требует TLS 1.2+ и ALPN (Application-Layer Protocol Negotiation).
🔹 В JDK 11+ ALPN встроен вsun.Безопасность.ssl.ALPNExtension.
10.1.5. Асинхронные операции
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/Данные"))
.timeout(Duration.ofSeconds(30)) // read timeout
.header("User-Agent", "MyApp/1.0")
.GET()
.build();
// Блокирующий вызов
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Асинхронный вызов (CompletableFuture)
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
10.1.6. Тела запросов
| Тип | Метод | Пример |
|---|---|---|
| Строка | BodyPublishers.ofString("text") | POST("text", BodyPublishers.ofString(body)) |
| Файл | BodyPublishers.ofFile(path) | PUT(BodyPublishers.ofFile(Paths.get("Данные.json"))) |
| Поток | BodyPublishers.ofInputStream(() -> in) | POST(BodyPublishers.ofInputStream(() -> new ByteArrayInputStream(bytes))) |
| Reactive | BodyPublishers.fromPublisher(publisher) | Для Flow API |
10.1.7. Обработка ответов
| Обработчик | Описание |
|---|---|
BodyHandlers.ofString() | Строка (по умолчанию UTF-8) |
BodyHandlers.ofInputStream() | InputStream (ленивая загрузка) |
BodyHandlers.ofFile(path) | Сохранение в файл |
BodyHandlers.discarding() | Игнорирование тела |
BodyHandlers.ofLines() | Stream<String> по строкам |
BodyHandlers.fromLineSubscriber(subscriber) | Reactive streams |
10.2. HttpURLConnection / URLConnection (legacy)
10.2.1. Базовое использование
URL url = new URL("https://api.example.com/Данные");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(10_000);
conn.setReadTimeout(30_000);
conn.setRequestProperty("User-Agent", "MyApp/1.0");
int status = conn.getResponseCode();
String body;
try (InputStream in = conn.getInputStream()) {
body = new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
10.2.2. Настройки подключения
| Метод | Описание |
|---|---|
setConnectTimeout(int ms) | Таймаут установки TCP-соединения |
setReadTimeout(int ms) | Таймаут между байтами при чтении |
setUseCaches(boolean) | Использовать кэш (только для GET, если ResponseCache установлен) |
setChunkedStreamingMode(int chunklen) | Отправка тела чанками (для больших POST) |
setFixedLengthStreamingMode(int len) | Фиксированная длина тела (Content-Length) |
setInstanceFollowRedirects(boolean) | Следовать редиректам (по умолчанию true) |
10.2.3. Кэширование
ResponseCache.setDefault(new MyResponseCache());
// MyResponseCache extends ResponseCache
public CacheResponse get(URI uri, String rqstMethod, Map<String, List<String>> rqstHeaders) { … }
public CacheRequest put(URI uri, URLConnection conn) throws IOException { … }
Поддерживается только для GET, HEAD.
10.3. Прокси-настройки
10.3.1. Глобальные настройки
Через системные свойства:
-Dhttp.proxyHost=proxy.local -Dhttp.proxyPort=3128
-Dhttps.proxyHost=proxy.local -Dhttps.proxyPort=3128
-Dhttp.nonProxyHosts="localhost|127.0.0.1|*.intranet"
10.3.2. Программные настройки
Для HttpClient:
ProxySelector proxySelector = ProxySelector.of(new InetSocketAddress("proxy.local", 3128));
HttpClient client = HttpClient.newBuilder()
.proxy(proxySelector)
.build();
Или кастомный:
ProxySelector customSelector = new ProxySelector() {
@Override
public List<Proxy> select(URI uri) {
if (uri.getHost().endsWith(".intranet")) {
return List.of(Proxy.NO_PROXY);
}
return List.of(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.local", 3128)));
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
logger.warn("Proxy failed for {}: {}", uri, sa, ioe);
}
};
Для HttpURLConnection:
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.local", 3128));
HttpURLConnection conn = (HttpURLConnection) new URL("https://example.com").openConnection(proxy);
10.4. TLS/SSL-конфигурация
10.4.1. Создание SSLContext
KeyStore trustStore = KeyStore.getInstance("JKS");
try (InputStream in = Files.newInputStream(Paths.get("trust.jks"))) {
trustStore.load(in, "changeit".toCharArray());
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, tmf.getTrustManagers(), null);
10.4.2. SSLParameters
SSLParameters params = sslContext.getDefaultSSLParameters();
// Протоколы
params.setProtocols(new String[]{"TLSv1.2", "TLSv1.3"});
// Шифронаборы
params.setCipherSuites(new String[]{
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
});
// ALPN (для HTTP/2)
params.setApplicationProtocols(new String[]{"h2", "http/1.1"});
// Hostname verification
params.setEndpointIdentificationAlgorithm("HTTPS"); // включает проверку CN/SAN
🔹
setEndpointIdentificationAlgorithm("HTTPS")— аналогHttpsURLConnection.getDefaultHostnameVerifier().
10.4.3. Отключение проверки сертификатов (только для тестов!)
TrustManager[] trustAll = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAll, new SecureRandom());
HttpClient client = HttpClient.newBuilder()
.sslContext(sslContext)
.sslParameters(new SSLParameters())
.build();
❌ Запрещено в production.
10.5. Аутентификация
10.5.1. Authenticator (глобальный)
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if ("api.example.com".equals(getRequestingHost())) {
return new PasswordAuthentication("user", "pass".toCharArray());
}
return super.getPasswordAuthentication();
}
});
Поддерживает:
- Basic;
- Digest;
- NTLM (на Windows);
- Negotiate (Kerberos/SPNEGO, если настроен JAAS).
10.5.2. Явные заголовки
String credentials = Base64.getEncoder().encodeToString("user:pass".getBytes(UTF_8));
HttpRequest request = HttpRequest.newBuilder()
.header("Authorization", "Basic " + credentials)
.GET()
.build();
10.5.3. OAuth2 / Bearer
HttpRequest request = HttpRequest.newBuilder()
.header("Authorization", "Bearer " + accessToken)
.GET()
.build();
10.6. Управление cookie
10.6.1. CookieHandler
CookieManager cookieManager = new CookieManager(
new FileCookieStore(Paths.get("cookies.txt")), // кастомный хранилище
CookiePolicy.ACCEPT_ORIGINAL_SERVER
);
HttpClient client = HttpClient.newBuilder()
.cookieHandler(cookieManager)
.build();
Политики:
CookiePolicy.ACCEPT_ALL— принимать все;CookiePolicy.ACCEPT_NONE— игнорировать;CookiePolicy.ACCEPT_ORIGINAL_SERVER— только от исходного домена (без 3rd-party).
10.6.2. Ручное управление
HttpResponse<String> loginResponse = client.send(loginRequest, BodyHandlers.ofString());
String cookies = loginResponse.headers().firstValue("Set-Cookie").orElse("");
HttpRequest dataRequest = HttpRequest.newBuilder()
.header("Cookie", cookies)
.GET()
.build();
10.7. HTTP/2 и ALPN
10.7.1. Требования для HTTP/2
- HTTPS (TLS 1.2+);
- Поддержка ALPN на сервере;
SSLParameters.setApplicationProtocols(new String[]{"h2", "http/1.1"});- JDK ≥ 9 (ALPN встроен).
10.7.2. Проверка версии
HttpResponse<Void> response = client.send(request, BodyHandlers.discarding());
System.out.println(response.version()); // HTTP_2 или HTTP_1_1
10.7.3. HTTP/3 (QUIC)
- В JDK не поддерживается (на 2025 год);
- Требует сторонних библиотек: AHC (Async HTTP Client), Jetty HttpClient, Netty.
10.8. Безопасность: OCSP, CRL, Hostname Verification
10.8.1. Включение OCSP stapling
Безопасность.setProperty("ocsp.enable", "true");
10.8.2. Проверка отзыва сертификатов
Система.setProperty("com.sun.net.ssl.checkRevocation", "true");
Безопасность.setProperty("jdk.Безопасность.certpath.revocationCheck", "PREFER_CRLS");
Возможные значения:
PREFER_CRLS— сначала CRL, потом OCSP;PREFER_OCSP— наоборот;NO_FALLBACK— без отката.
10.8.3. Hostname verification
- По умолчанию в
HttpsURLConnectionиHttpClient— включена приsetEndpointIdentificationAlgorithm("HTTPS"); - Проверяет:
SubjectAlternativeName(SAN) DNS-имена;- при отсутствии SAN —
CommonName(CN) вSubjectDN; - нечувствительно к регистру;
- поддерживает wildcard (
*.example.com→api.example.com, но неa.b.example.com).
10.9. Диагностика и отладка
10.9.1. Логирование SSL
-Djavax.net.debug=ssl:handshake:verbose
10.9.2. Трассировка HTTP
HttpClient client = HttpClient.newBuilder()
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/get"))
.header("User-Agent", "Debug")
.GET()
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Headers: " + response.headers().map());
System.out.println("Body: " + response.body());
10.9.3. Перехват запросов/ответов
Через HttpClient.Builder.executor() и кастомный Flow.Subscriber, или через прокси (mitmproxy, Charles).
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). JDK (Java Разработка Kit) — полный комплект разработчика. Включает — Компилятор javac для преобразования исходного кода в байт-код, Виртуальную машину JVM для выполнения байт-кода, Стандартные… Фундамент для начинающего программиста - что повторить, как работать, чего ожидать. Набор советов, правил, принципов и обычаев в разработке на этом языке. Use-after-free — это обращение к участку памяти после его освобождения. Программа продолжает использовать указатель на объект, память которого уже возвращена системе управления памятью. Библиотеки, фреймворки, инструменты сборки, тестирования, развёртывания и мониторинга. Что такое пакет и пакетная структура, как собираются проекты на Java. Гайд по установке и настройке с написанием первой программы и её запуском. Примеры простых и полезных консольных приложений с демонстрацией концепций языка. Кавычки, точки, запятые, скобки и прочие знаки препинания. Это полный справочник всех ключевых слов языка Java, включая основные, контекстные и зарезервированные слова. Набор функций, которые включены в стандартную библиотеку языка. Типизация, набор правил определения типа данных значений языка.Основы языка Java
Что требуется знать перед началом изучения языка программирования Java
Рекомендации по разработке на Java
История языка Java
Экосистема Java-приложений
Структура и сборки Java-проектов
Первая программа на Java
Простые приложения на Java
Синтаксис и пунктуация в Java
Ключевые слова в Java
Встроенные функции и методы Java
Типы данных и переменные в Java