предисловие
через предыдущийJVMЗнание сборки мусора, мы понимаемJVMконкретныйАлгоритм сборки мусораи несколькоуборщик мусора. Теория — это инструмент, которым можно руководствоваться на практике.При теоретическом руководстве при выявлении проблем знания и опыт являются ключевым фундаментом, а данные могут дать нам основу.
В сети мы часто сталкиваемся со следующими проблемами:
- утечка памяти;
- процесс внезапно
CPUпарить; - тупик резьбы;
- Медленный ответ.
Если вы столкнулись с вышеуказанной проблемой, вавтономная средаможет иметь различныеНативные визуальные инструментыПоддержка просмотра. Но как только он приходитонлайн-среда, не так многолокальные средства отладкиподдержку, как мы можем опираться наинструмент мониторингадля проблем с позиционированием?
Обычно мы основываемся наСбор данныхлокализовать проблему, а сбор данных неотделим отинструмент мониторингаобработка, например:журнал выполнения,стек исключений,GC бревно,снимок потока,моментальный снимок кучи памятиЖдать. Для решения вышеуказанных проблем мы обычно используемJVM Средство мониторинга настройки производительностиГрубо:jps,jstat,jstack,jmap,jhat,hprof,jinfo.
текст
Если вы хотите увидетьJavaв ходе выполнениястек потоковинформация, вы можете выбратьjstackЗаказ. Если вы хотите увидетькуча памяти,можно использоватьjmapэкспортировать и использоватьjhatдля анализа, включая просмотринформация о загрузке класса,GC алгоритм,объектиспользование и т. д. можно использоватьjstatиди прямоJVMпровестиСтатистический мониторинг, включая просмотр каждогообласть памятииGCслучае, вы также можете использоватьhprofПроверятьCPU использование,статистикакуча памятииспользование. Использование этих инструментов будет подробно описано ниже.
Общие инструменты и инструкции для мониторинга JVM
1. инструмент мониторинга процессов jps
jpsиспользуется, чтобы увидеть, кто имеет доступhotspot виртуальная машинапроцесс. когда не указаноhostid, вид по умолчаниюродной jvmпроцесс, в противном случае просмотреть указанныйhostidна машинеjvmпроцесс, в это времяhostidУказанный автомат должен быть включенjstatdСлужить.
jpsмогу перечислитьjvmпроцессlvmid,имя основного класса,mainпараметры функции,jvmпараметр,jarимя и другие данные.
Формат команды следующий:
usage: jps [-help]
jps [-q] [-mlvV] [<hostid>]
Definitions:
<hostid>: <hostname>[:<port>]
Смысл параметров следующий:
- -q: не выводитьимя класса,
Jarназваниеи входящийmainметодпараметр; - -л: вывод
mainкласс илиJarизПолное имя; - -m: вывод входящий
mainметодпараметр; - -v: вывод входящий
JVMпараметр.
2. инструмент просмотра информации о конфигурации jinfo
jinfo(JVM Configuration info) Эта команда используется для просмотра и настройки в режиме реального времени.Параметры работы виртуальной машины. предыдущийjps -vкоманду можно увидеть только для отображениязаданные параметры, если хочешь посмотретьне показаноБудет использовано значение параметраjinfoЗаказ.
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
Смысл параметров следующий:
- идентификатор: местный
jvmпроцесс обслуживанияID; - исполняемое ядро: печатьтрассировки стекаосновной документ;
- IP-адрес/имя хоста удаленного сервера: удаленный
debugУслугиИмя процессораилиIPадрес; - идентификатор сервера: удаленный
debugУслугипроцессID.
Варианты параметров описаны следующим образом:
| параметр | Значение параметра |
|---|---|
| flag | выходное обозначениеargsзначение параметра |
| flags | ненужныйargsпараметры, вывести всеJVMзначение параметра |
| sysprops | выходные свойства системы, эквивалентныеSystem.getProperties()
|
- Посмотреть работает
jvmпроцессРасширенные параметры.
$ jinfo -flags 31983
Attaching to process ID 31983, please wait…
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b14
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=20971520 -XX:MaxHeapFreeRatio=90 -XX:MaxHeapSize=20971520 -XX:MaxNewSize=2097152 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=2097152 -XX:OldSize=18874368 -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line: -Xmx20m -Xms20m -Xmn2m -javaagent:/opt/idea-IU-181.4668.68/lib/idea_rt.jar=34989:/opt/idea-IU-181.4668.68/bin -Dfile.encoding=UTF-8
- Посмотреть работает
jvmвесь процессИнформация о параметрах.
$ jinfo 31983
Attaching to process ID 31983, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b14
Java System Properties:
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.91-b14
sun.boot.library.path = /opt/jdk1.8.0_91/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = CN
user.dir = /home/linchen/projects
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_91-b14
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /opt/jdk1.8.0_91/jre/lib/endorsed
java.io.tmpdir = /tmp
line.separator =
java.vm.specification.vendor = Oracle Corporation
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 4.15.0-24-generic
user.home = /home/linchen
user.timezone =
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = linchen
java.class.path = /opt/jdk1.8.0_91/jre/lib/charsets.jar:/opt/jdk1.8.0_91/jre/lib/deploy.jar:/opt/jdk1.8.0_91/jre/lib/ext/cldrdata.jar:/opt/jdk1.8.0_91/jre/lib/ext/dnsns.jar:/opt/jdk1.8.0_91/jre/lib/ext/jaccess.jar:/opt/jdk1.8.0_91/jre/lib/ext/jfxrt.jar:/opt/jdk1.8.0_91/jre/lib/ext/localedata.jar:/opt/jdk1.8.0_91/jre/lib/ext/nashorn.jar:/opt/jdk1.8.0_91/jre/lib/ext/sunec.jar:/opt/jdk1.8.0_91/jre/lib/ext/sunjce_provider.jar:/opt/jdk1.8.0_91/jre/lib/ext/sunpkcs11.jar:/opt/jdk1.8.0_91/jre/lib/ext/zipfs.jar:/opt/jdk1.8.0_91/jre/lib/javaws.jar:/opt/jdk1.8.0_91/jre/lib/jce.jar:/opt/jdk1.8.0_91/jre/lib/jfr.jar:/opt/jdk1.8.0_91/jre/lib/jfxswt.jar:/opt/jdk1.8.0_91/jre/lib/jsse.jar:/opt/jdk1.8.0_91/jre/lib/management-agent.jar:/opt/jdk1.8.0_91/jre/lib/plugin.jar:/opt/jdk1.8.0_91/jre/lib/resources.jar:/opt/jdk1.8.0_91/jre/lib/rt.jar:/home/linchen/IdeaProjects/core_java/target/classes:/home/linchen/.m2/repository/io/netty/netty-all/4.1.7.Final/netty-all-4.1.7.Final.jar:/home/linchen/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/linchen/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/home/linchen/.m2/repository/com/lmax/disruptor/3.3.0/disruptor-3.3.0.jar:/home/linchen/.m2/repository/com/rabbitmq/amqp-client/5.3.0/amqp-client-5.3.0.jar:/home/linchen/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/opt/idea-IU-181.4668.68/lib/idea_rt.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = com.own.learn.jvm.JinfoTest
java.home = /opt/jdk1.8.0_91/jre
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_91
java.ext.dirs = /opt/jdk1.8.0_91/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /opt/jdk1.8.0_91/jre/lib/resources.jar:/opt/jdk1.8.0_91/jre/lib/rt.jar:/opt/jdk1.8.0_91/jre/lib/sunrsasign.jar:/opt/jdk1.8.0_91/jre/lib/jsse.jar:/opt/jdk1.8.0_91/jre/lib/jce.jar:/opt/jdk1.8.0_91/jre/lib/charsets.jar:/opt/jdk1.8.0_91/jre/lib/jfr.jar:/opt/jdk1.8.0_91/jre/classes
java.vendor = Oracle Corporation
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.desktop = gnome
sun.cpu.isalist =
VM Flags:
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=20971520 -XX:MaxHeapFreeRatio=90 -XX:MaxHeapSize=20971520 -XX:MaxNewSize=2097152 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=2097152 -XX:OldSize=18874368 -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC
Command line: -Xmx20m -Xms20m -Xmn2m -javaagent:/opt/idea-IU-181.4668.68/lib/idea_rt.jar=34989:/opt/idea-IU-181.4668.68/bin -Dfile.encoding=UTF-8
- Посмотреть работает
jvmпроцессинформация о переменной окружения.
$ jinfo -sysprops 31983
Attaching to process ID 31983, please wait…
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b14
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.91-b14
sun.boot.library.path = /opt/jdk1.8.0_91/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = CN
user.dir = /home/linchen/projects
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_91-b14
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /opt/jdk1.8.0_91/jre/lib/endorsed
java.io.tmpdir = /tmp
line.separator =
2. инструмент мониторинга информационной статистики jstat
jstatиспользуется для идентификациивиртуальная машинаразныеинформация о рабочем состоянииинструмент командной строки. это может показатьместныйилиудаленная виртуальная машинав ходе выполнениязагрузка класса,ОЗУ,вывоз мусора,jit компилироватьи т.д. бегущие данные, этоонлайндолжностьjvm представлениеинструмент на выбор.
jstatИнструмент обеспечивает следующееjvmФункция мониторинга:
- загрузка классаиудалитьСлучай;
- ПроверятьКайнозой,старое поколениеиметапространство(
MetaSpace)иземкостьи использование; - ПроверятьКайнозой,старое поколениеиметапространство(
MetaSpace)изСитуация с вывозом мусора, включая сбор мусорачастота, занят сборкой мусоравремя; - ПроверятьКайнозойсередина
EdenРайон иSurviorОкругемкостьираспределениеЖдать.
Формат команды следующий:
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Смысл параметров следующий:
- опция: опция параметра.
- -t: можно добавить в печатный столбец
timestampСтолбцы, показывающие, как долго работает система. - -h: может использоваться вПериодические данные, вы можете вывести один раз, указав, сколько строк выводитьзаголовок.
- -t: можно добавить в печатный столбец
- vmid: ID виртуальной машины (имя процесса
pid). - lines: заголовокизаголовокКоличество строк интервала.
- интервал: выполнять каждый разИнтервалы, единицамиллисекунда.
- count: используется для указания количества выходных записейчастота, по умолчанию всегда будет печататься.
Варианты параметров описаны следующим образом:
- класс: шоузагрузка класса
ClassLoadрелевантная информация; - компилятор: показать
JITкомпилироватьрелевантная информация; - gc: показать и
gcСвязанныйинформация о куче; - gccapacity: показатьвсе поколенияиземкостьа такжеиспользование;
- gcmetacapacity: показатьметапространство
metaspaceразмер; - gcnew: показатьКайнозойИнформация;
- gcnewcapacity: показатьразмер молодого поколенияииспользование;
- гхолод: показатьстаростьипостоянное поколениеИнформация;
- gcoldcapacity: показатьстаростьразмер;
- gcutil: показатьИнформация о сборе мусора;
- gcпричина: показатьвывоз мусорасвязанная информация (такая же, как
-gcutil), при отображениипоследний разилиТекущийпроисходит сбор мусораСтимул; - компиляция печати: вывод
JITкомпилироватьинформация о методе;
2.1. class
дисплей и мониторзагрузка класса,Количество удалений,общая площадьа такжепроведенное время.
$ jstat -class 8615
Loaded Bytes Unloaded Bytes Time
7271 13325.8 1 0.9 2.98
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| Loaded | количество загруженных классов |
| Bytes | Количество байтов, занимаемых загруженным классом |
| Unloaded | Количество удаленных классов |
| Bytes | Байты выгруженных классов |
| Time | Время, потраченное на загрузку и выгрузку классов |
2.2. compiler
показать виртуальную машинуСвоевременная компиляция(JIT)изчастотаикропотливыйи другая информация.
$ jstat -compiler 8615
Compiled Failed Invalid Time FailedType FailedMethod
3886 0 0 1.29 0
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| Compiled | Количество выполненных задач компиляции |
| Failed | Количество неудачных задач компиляции |
| Invalid | Номер ошибки выполнения задачи компиляции |
| Time | Задача компиляции требует времени |
| FailedType | Тип последней задачи, которую не удалось скомпилировать |
| FailedMethod | Класс и метод последней неудачной задачи компиляции |
2.3. gc
показыватьвывоз мусора(gc)Связанныйинформация о куче,Проверятьgcизчастотаивремя.
$ jstat -gc 8615
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
20480.0 10752.0 0.0 0.0 262128.0 130750.7 165376.0 24093.7 35456.0 33931.0 4992.0 4582.0 5 0.056 2 0.075 0.131
Например, следующий выводGCинформация, выборкавременной интервалза250ms, количество выборок4:
$ jstat -gc 8615 250 4
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
20480.0 10752.0 0.0 0.0 262144.0 130750.7 165376.0 24093.7 35456.0 33931.0 4992.0 4582.0 5 0.056 2 0.075 0.131
20480.0 10752.0 0.0 0.0 262872.0 130750.7 165376.0 24093.7 35456.0 33931.0 4992.0 4582.0 5 0.056 2 0.075 0.131
20480.0 10752.0 0.0 0.0 262720.0 130750.7 165376.0 24093.7 35456.0 33931.0 4992.0 4582.0 5 0.056 2 0.075 0.131
20480.0 10752.0 0.0 0.0 262446.0 130750.7 165376.0 24093.7 35456.0 33931.0 4992.0 4582.0 5 0.056 2 0.075 0.131
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| S0C | Первый из молодого поколенияsurvivorемкость |
| S1C | второй в молодом поколенииsurvivorемкость |
| S0U | Первый из молодого поколенияsurvivorпространство, используемое в настоящее время |
| S1U | второй в молодом поколенииsurvivorпространство, используемое в настоящее время |
| EC | молодое поколениеEdenемкость |
| EU | молодое поколениеEdenпространство, используемое в настоящее время |
| OC | дееспособность в старости |
| OU | Старость в настоящее время используется пространство |
| MC | метапространствоmetaspaceемкость |
| MU | метапространствоmetaspaceпространство, используемое в настоящее время |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgc частота
|
| YGCT | От запуска приложения до времени выборкимолодое поколениесерединаgc Время, потраченное
|
| FGC | От запуска приложения до времени выборкистаростьсерединаgc частота
|
| FGCT | От запуска приложения до времени выборкистаростьсерединаgc Время, потраченное
|
| GCT | От запуска приложения до времени выборкиgcиспользоватьобщее время
|
2.4. gccapacity
показыватьпамять виртуальной машинысреднее и третье поколениемолодое поколение(young),старость(old),метапространство(metaspace) использование объекта и занимаемый размер.
$ jstat -gccapacity 8615
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
87040.0 1397760.0 372736.0 20480.0 10752.0 262144.0 175104.0 2796544.0 165376.0 165376.0 0.0 1079296.0 35456.0 0.0 1048576.0 4992.0 5 2
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| NGCMN | молодое поколениеинициализация(минимальная) емкость |
| NGCMX | молодое поколениеМаксимальная емкость |
| NGC | молодое поколениетекущая вместимость |
| S0C | молодое поколениеПервый survivorЕмкость района |
| S1C | молодое поколениесекунда survivorЕмкость района |
| EC | молодое поколениеEden(Эдемский сад) емкость |
| OGCMN | средний возрастинициализация(минимальная) емкость |
| OGCMX | старостьМаксимальная емкость |
| OGC | старостьтекущая новая сборкаемкость |
| OC | дееспособность в старости |
| MCMN | метапространствоизИнициализировать емкость |
| MCMX | метапространствоизМаксимальная емкость |
| MC | метапространствоТекущийвновь сгенерированныйемкость |
| CCSMN | минимумРазмер пространства сжатого класса |
| CCSMX | максимумРазмер пространства сжатого класса |
| CCSC | ТекущийРазмер пространства сжатого класса |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgcчастота |
| FGC | От запуска приложения до времени выборкистаростьсерединаgcчастота |
2.5. gcmetacapacity
показыватьметапространство(metaspace)серединаобъектинформация и ее заполняемость.
$ jstat -gcmetacapacity 8615
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1079296.0 35456.0 0.0 1048576.0 4992.0 5 2 0.075 0.131
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| MCMN | минимумЕмкость пространства метаданных |
| MCMX | максимумЕмкость пространства метаданных |
| MC | ТекущийЕмкость пространства метаданных |
| CCSMN | минимальное сжатиеВместимость класса |
| CCSMX | максимальное сжатиеВместимость класса |
| CCSC | ТекущийЕмкость сжатого пространства |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgcчастота |
| FGC | От запуска приложения до времени выборкистаростьсерединаgcчастота |
| FGCT | От запуска приложения до времени выборкистарость gc Время, потраченное
|
| GCT | От запуска приложения до времени выборкиgcиспользоватьобщее время
|
2.6. gcnew
показыватьОбъекты молодого поколенияинформация, в том числе дваsurvivorРайон иEdenПлощадь.
$ jstat -gcnew 8615
S0C S1C S0U S1U TTv MTT DSS EC EU YGC YGCT
20480.0 10752.0 0.0 0.0 6 15 20480.0 262144.0 131406.0 5 0.056
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| S0C | Первый из молодого поколенияsurvivorемкость |
| S1C | второй в молодом поколенииsurvivorемкость |
| S0U | Первый из молодого поколенияsurvivorпространство, используемое в настоящее время |
| S1U | второй в молодом поколенииsurvivorпространство, используемое в настоящее время |
| TT | Ограничение количества удержаний |
| MTT | Максимальное количество владений |
| DSS | ОжидалЗона выживанияразмер |
| EC | молодое поколениеEdenемкость |
| EU | молодое поколениеEdenпространство, используемое в настоящее время |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgc частота
|
| YGCT | От запуска приложения до времени выборкимолодое поколениесерединаgc Время, потраченное
|
2.7. gcnewcapacity
Проверятьмолодое поколениеИнформация об объекте и его заполняемости.
$ jstat -gcnewcapacity 8615
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
87040.0 1397760.0 372736.0 465920.0 20480.0 465920.0 10752.0 1396736.0 262144.0 5 2
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| NGCMN | Инициализированный (минимальный) размер в молодом поколении |
| NGCMX | Максимальный потенциал молодого поколения |
| NGC | Текущий потенциал в молодом поколении |
| S0CMX | Первый из молодого поколенияsurvivorмаксимальная вместимость |
| S0C | Первый из молодого поколенияsurvivorемкость |
| S1CMX | второй в молодом поколенииsurvivorмаксимальная вместимость |
| S1C | второй в молодом поколенииsurvivorемкость |
| ECMX | молодое поколениеEdenмаксимальная вместимость |
| EC | молодое поколениеEdenемкость |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgcчастота |
| FGC | От запуска приложения до времени выборкистаростьсерединаgcчастота |
2.8. gcold
показыватьобъект старостисвязанная информация.
$ jstat -gcold 8615
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
35456.0 33931.0 4992.0 4582.0 165376.0 24093.7 5 2 0.075 0.131
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| MC |
метапространство(metaspace) емкость |
| MU |
метапространство(metaspace) используемое в настоящее время пространство |
| CCSC | Размер пространства сжатого класса |
| CCSU | Сжатое пространство классаиспользоватьразмер |
| OC | старостьемкость |
| OU | старостьпространство, используемое в настоящее время |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgcчастота |
| FGC | От запуска приложения до времени выборкистаростьсерединаgcчастота |
| FGCT | От запуска приложения до времени выборкистарость gc Время, потраченное
|
| GCT | От запуска приложения до времени выборкиgcиспользоватьобщее время
|
2.9. gcoldcapacity
ПроверятьстаростьИнформация об объекте и его заполняемости.
$ jstat -gcoldcapacity 8615
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
175104.0 2796544.0 165376.0 165376.0 5 2 0.075 0.131
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| OGCMN | старостьИнициализированный (минимальный) размер в |
| OGCMX | старостьмаксимальная вместимость |
| OGC | старостьТекущая вновь созданная мощность |
| OC | старостьемкость |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgcколичество раз |
| FGC | От запуска приложения до времени выборкистаростьсерединаgcколичество раз |
| FGCT | От запуска приложения до времени выборкистаростьсерединаgcВремя, потраченное |
| GCT | От запуска приложения до времени выборкиgcиспользоватьобщее время
|
2.10. gcutil
показыватьвывоз мусора(gc) обрабатывать информацию, включая каждуюкоэффициент использования памяти, вывоз мусоравремяи переработкачастота.
$ jstat -gcutil 8615
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 50.13 14.57 95.70 91.79 5 0.056 2 0.075 0.131
Список параметров и их значения следующие:
| параметр | Значение параметра |
|---|---|
| S0 | молодое поколениеПервый survivorПлощадьИспользовал% текущей емкости |
| S1 | молодое поколениесекунда survivorПлощадьИспользовал% текущей емкости |
| E | молодое поколениеEdenПлощадьИспользовал% текущей емкости |
| O | старостьсерединаИспользовал% текущей емкости |
| M |
метапространство(metaspace)серединаИспользовал% текущей емкости |
| YGC | От запуска приложения до времени выборкимолодое поколениесерединаgc частота
|
| YGCT | От запуска приложения до времени выборкимолодое поколениесерединаgc Время, потраченное
|
| FGC | От запуска приложения до времени выборкистарость gc частота
|
| FGCT | От запуска приложения до времени выборкистарость gc Время, потраченное
|
| GCT | От запуска приложения до времени выборкиgcиспользоватьобщее время
|
3. инструмент статистики памяти кучи jmap
jmap (JVM Memory Map) команда для просмотракуча памятииспользование, как правило, в сочетанииjhatиспользовать для созданияheap dumpдокумент.jmapне только может генерироватьdumpфайл, вы также можете запроситьfinalize очередь выполнения,Java кучаиметапространство metaspaceтакие детали, как текущаяиспользование, который используется в настоящее времяколлекционери Т. Д.
Если вы не используете эту команду, вы также можете использовать
-XX:+HeapDumpOnOutOfMemoryErrorпараметры для отображения виртуальной машиныOOMгенерируется автоматически, когдаdumpдокумент.
Формат команды следующий:
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
Смысл параметров следующий:
- идентификатор: местный
jvmпроцесс обслуживанияID; - исполняемое ядро: печатьтрассировки стекаосновной документ;
- IP-адрес/имя хоста удаленного сервера: удаленный
debugУслугиИмя процессораилиIPадрес; - идентификатор сервера: удаленный
debugУслугипроцессID.
Варианты параметров описаны следующим образом:
| параметр | Значение параметра |
|---|---|
| heap | показыватькучаСводная информация в |
| histo | показыватькучаСтатистика по объектам в |
| histo[:live] | покажи толькокучасерединауцелевший объектстатистика |
| clstats | показыватьзагрузка классастатистика |
| finalizerinfo | покажитеF-Queue очередьждатьFinalizerвыполнение потокаfinalizerобъект метода |
| dump | Экспорт снимка дампа памяти |
Уведомление:
dumpАнализ моментальных снимков памяти в основном состоит изhisto,clstats,finalizerinfoи другие функции.
3.1. heap
показыватькучаСводная информация в формате . включаюткуча памятииспользование, используетGC алгоритм,Параметры конфигурации кучииКуча памяти в каждом поколениииспользование. Вы можете использовать это, чтобы определить текущую памятьиспользованиеа такжевывоз мусорасостояние.
$ jmap -heap 11368
Attaching to process ID 11368, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.101-b13
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2684354560 (2560.0MB)
NewSize = 1073741824 (1024.0MB)
MaxNewSize = 1073741824 (1024.0MB)
OldSize = 1610612736 (1536.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 852492288 (813.0MB)
used = 420427144 (400.95056915283203MB)
free = 432065144 (412.04943084716797MB)
49.31741317993014% used
From Space:
capacity = 113770496 (108.5MB)
used = 2299712 (2.19317626953125MB)
free = 111470784 (106.30682373046875MB)
2.021360617079493% used
To Space:
capacity = 107479040 (102.5MB)
used = 0 (0.0MB)
free = 107479040 (102.5MB)
0.0% used
PS Old Generation
capacity = 1610612736 (1536.0MB)
used = 50883368 (48.526161193847656MB)
free = 1559729368 (1487.4738388061523MB)
3.1592552860577903% used
27595 interned Strings occupying 3138384 bytes.
В основном здесьheap configurationСписок параметров поясняет:
| параметр | Соответствующие параметры запуска | Значение параметра |
|---|---|---|
| MinHeapFreeRatio | -XX:MinHeapFreeRatio | Минимальный коэффициент простоя кучи JVM (по умолчанию 40) |
| MaxHeapFreeRatio | -XX:MaxHeapFreeRatio | Максимальный коэффициент простоя кучи JVM (по умолчанию 70) |
| MaxHeapSize | XX:Xmx | Максимальный размер кучи JVM |
| NewSize | -XX:NewSize | Размер по умолчанию (инициализированный) кучи JVM молодого поколения |
| MaxNewSize | -XX:MaxNewSize | Максимальный размер молодого поколения кучи JVM |
| OldSize | -XX:OldSize | Размер по умолчанию (инициализация) старого поколения кучи JVM |
| NewRatio | -XX:NewRatio | Соотношение размера кучи JVM для молодого поколения и старого поколения |
| SurvivorRatio | -XX:SurvivorRatio | Отношение размера области Eden к области Survivor в молодом поколении кучи JVM |
| MetaspaceSize | -XX:MetaspaceSize | Размер инициализации метапространства JVM |
| MaxMetaspaceSize | -XX:MaxMetaspaceSize | Максимальный размер метапространства JVM (метапространства) |
| CompressedClass SpaceSize | -XX:CompressedClass SpaceSize | Размер области сжатия указателя класса JVM, по умолчанию 1G |
| G1HeapRegionSize | -XX:G1HeapRegionSize | Размер одного региона при использовании сборщика мусора G1: от 1 до 32 МБ. |
3.2. histo
куча печатиСтатистика объекта,включаютколичество экземпляров объекта,объем памятии Т. Д. Так какhisto:liveбудет осуществляться доfull gc, если принестиliveтолько статистикаживой объект. не добавлятьliveРазмер кучи больше, чем плюсliveРазмер кучи.
$ jmap -histo:live 12498
num #instances #bytes class name
----------------------------------------------
1: 50358 7890344 [C
2: 22887 2014056 java.lang.reflect.Method
3: 3151 1485512 [B
4: 49267 1182408 java.lang.String
5: 7836 871384 java.lang.Class
6: 24149 772768 java.util.concurrent.ConcurrentHashMap$Node
7: 20785 482256 [Ljava.lang.Class;
8: 8357 435248 [Ljava.lang.Object;
9: 10035 401400 java.util.LinkedHashMap$Entry
10: 4803 369488 [Ljava.util.HashMap$Node;
11: 10763 344416 java.util.HashMap$Node
12: 5205 291480 java.util.LinkedHashMap
13: 3055 219960 java.lang.reflect.Field
14: 120 193408 [Ljava.util.concurrent.ConcurrentHashMap$Node;
15: 11224 179584 java.lang.Object
16: 1988 146152 [Ljava.lang.reflect.Method;
17: 3036 145728 org.aspectj.weaver.reflect.ShadowMatchImpl
18: 1771 141680 java.lang.reflect.Constructor
19: 4903 117672 org.springframework.core.MethodClassKey
20: 3263 104416 java.lang.ref.WeakReference
21: 2507 100280 java.lang.ref.SoftReference
22: 2523 97600 [I
23: 3036 97152 org.aspectj.weaver.patterns.ExposedState
24: 2072 95280 [Ljava.lang.String;
25: 954 91584 org.springframework.beans.GenericTypeAwarePropertyDescriptor
26: 1633 91448 java.lang.Class$ReflectionData
27: 3142 90520 [Z
28: 1671 80208 java.util.HashMap
29: 3244 77856 java.util.ArrayList
30: 3037 72880 [Lorg.aspectj.weaver.ast.Var;
31: 1809 72360 java.util.WeakHashMap$Entry
32: 1967 62944 java.util.LinkedList
в,class nameдатип объекта, объектТип сокращенияиреальный типСоответствующее описание выглядит следующим образом:
| Аббревиатура объекта Тип | Реальный тип объекта |
|---|---|
| B | byte |
| C | char |
| D | double |
| F | float |
| I | int |
| J | long |
| Z | boolean |
| [ | Массив, например [I означает int[] |
| [L+имя класса | другие объекты |
3.3. dump
dumpИспользуется для экспорта моментальных снимков дампа памяти. Обычный путь черезjmapпоставить процессиспользование памяти dumpв файл, а затем используйтеjhatАналитический вид.jmapпровестиdumpФормат команды следующий:
jmap -dump:format=b,file=dumpFileName
Смысл параметров следующий:
| параметр | Значение параметра |
|---|---|
| dump | куча в файл |
| format | Укажите выходной формат |
| live | Указывает на живой объект |
| file | указать имя файла |
- пройти через
jmapэкспортснимок памяти, файл называетсяdump.dat:
jmap -dump:format=b,file=dump.dat 12498
Dumping heap to /Users/XXX/dump.dat ...
Heap dump file created
экспортируетсяdumpдоступ к файлам возможен черезMAT,VisualVMиjhatПроверьте анализ с другими инструментами, которые будут подробно описаны позже.
4. инструмент анализа моментальных снимков кучи jhat
jhat(JVM Heap Analysis Tool) команда обычно сочетается сjmapиспользуются вместе для анализаjmapСгенерированоdump.jhatпостроен в миниатюреHTTP/HTML сервер, сгенерироватьdumpРезультаты анализа можно просмотреть в браузере.
Примечание: как правило, не непосредственно всерверначальствоанализировать, потому что с помощью
jhatЯвляетсякропотливыйипотреблять аппаратные ресурсыпроцесс, общая практика заключается в том, чтобы поставитьсерверСгенерированоdumpфайл скопирован вместныйилидругие машиныанализ на.
Формат команды следующий:
Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
-J<flag> Pass <flag> directly to the runtime system. For
example, -J-mx512m to use a maximum heap size of 512MB
-stack false: Turn off tracking object allocation call stack.
-refs false: Turn off tracking of references to objects
-port <port>: Set the port for the HTTP server. Defaults to 7000
-exclude <file>: Specify a file that lists data members that should
be excluded from the reachableFrom query.
-baseline <file>: Specify a baseline object dump. Objects in
both heap dumps with the same ID and same class will
be marked as not being "new".
-debug <int>: Set debug level.
0: No debug output
1: Debug hprof file parsing
2: Debug hprof file parsing, no server
-version Report version number
-h|-help Print this help and exit
<file> The file to read
Смысл параметров следующий:
| параметр | значение параметра значение по умолчанию | Значение параметра |
|---|---|---|
| stack | true | закрытиеТрассировка стека вызовов выделения объектов. Если информация о размещении недоступна в дампе кучи. тогда этот флаг должен быть установлен в false. |
| refs | true | закрытиеотслеживание ссылок на объекты. По умолчанию возвращаемый указатель является объектом, указывающим на какой-то другой конкретный объект. какобратные ссылкииливведите цитату, будет считать/подсчитывать все объекты в куче |
| port | 7000 | Установите номер порта HTTP-сервера jhat |
| exclude | --- | Указывает файл списка элементов данных, который следует исключить при запросе объектов. |
| baseline | --- | указатьБазовый дамп кучи. Объекты с одинаковым идентификатором объекта в двух дампах кучи помечаются как не новые, а другие объекты помечаются как новые. Полезно при сравнении двух разных дампов кучи |
| debug | 0 | Установите уровень отладки, 0 означает, что информация об отладке не выводится. Чем больше значение, тем более подробная информация об отладке будет выводиться. |
| version | --- | После запуска отображать только информацию о версии и выходить |
| J | --- | Команда jhat фактически запустит JVM для выполнения, через -J вы можете передать некоторые параметры при запуске JVM.параметры запуска. Например, -J-Xmx512m указывает, что максимальный размер кучи, используемый виртуальной машиной Java, на которой работает jhat, составляет 512 МБ. |
- Как упоминалось ранее, через
jmap dumpВыходной файл можно использоватьMAT,VisualVMДождитесь просмотра инструментов, здесь мы используемjhatПроверять:
$ jhat -port 7000 dump.dat
Reading from dump.dat...
Dump file created Sun Aug 12 12:15:02 CST 2018
Snapshot read, resolving...
Resolving 1788693 objects...
Chasing references, expect 357 dots.....................................................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references.....................................................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
- Откройте браузер и введите
http://localhost:7000,ПроверятьjhatСтраница отчета об анализе:
- может следоватьимя пакетаПодробности смотрите в модуле проектаПример объекта:
Кроме того, последняя страница анализа отчета также предоставляет некоторые расширенные запросы:
- показать все
Rootсобирать; - показать все
classэлектрический токколичество экземпляров объекта(ВключаютJVMклассы, связанные с платформой); - показать все
classэлектрический токколичество экземпляров объекта(УдалитьJVMклассы, связанные с платформой); - показыватькуча памятиобъекта экземпляра вГистограмма статистики(и использовать непосредственно
jmapнет разницы); - показывать
finalizerвиртуальная машинаВторичная переработкасводка информации; - воплощать в жизнь
jhatкоторый предоставилЯзык объектных запросов(OQL) для получения информации об экземпляре указанного объекта.
Уведомление:
jhatподдержка на определенных условияхфильтрилиЗапроскуча предметов. допустимыйjhatизhtmlвыполнить на страницеOQLоператор для запроса объектов, соответствующих условиям.OQL`Конкретный синтаксис может быть доступен напрямуюhttp://локальный:7000/oqlhelp.
В конкретном расследовании необходимо комбинировать код, чтобы наблюдать,Многое должно быть переработаноОбъектвсегда цитируется, или есть лиЗанимает много памятиОбъектне может быть переработан.
5. инструмент трассировки стека jstack
jstackдля созданияjavaТекущий момент виртуальной машиныснимок потока.снимок потокаактуаленjavaВнутри виртуальной машиныкаждая нитьвыполняетсястек методовизсобирать. Основная цель создания моментальных снимков потоков — определить местонахождение потоков.долгая паузапричины, такие каквзаимоблокировка между потоками,бесконечный цикл,запрашивать внешние ресурсывызванныйдолгое ожиданиеи Т. Д.
появляется нитьПаузакогда черезjstackсмотретьотдельные темыизстек вызовов, вы можете узнать, что неотвечающий поток делает в фоновом режиме или какие ресурсы ждут. еслиjavaпрограммакрахгенерироватьcore документ,jstackинструменты могут бытьcoreполучение файлаjava stackиnative stackинформация для определения причины сбоя программы.
Формат команды следующий:
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Смысл параметров следующий:
- идентификатор: местный
jvmпроцесс обслуживанияID; - исполняемое ядро: печатьтрассировки стекаосновной документ;
- IP-адрес/имя хоста удаленного сервера: удаленный
debugУслугиИмя процессораилиIPадрес; - идентификатор сервера: удаленный
debugУслугипроцессID.
Варианты параметров описаны следующим образом:
| параметр | Значение параметра |
|---|---|
| F | При обычном запросе выводане отвечаетКогда выход принудительныйстек потоков |
| l | В дополнение к стеку, показать оДополнительная информация по замкам |
| m | если позватьсобственный методможет отображатьC/C++куча |
Примечание. В реальной эксплуатации часто один раз
dumpинформации недостаточно для подтверждения проблемы. Рекомендуется генерировать три разаdumpинформация, если каждый разdumpВсе указывают на одну и ту же проблему, чтобы определить типичность проблемы.
5.1 Статус системного потока
существуетdumpфайл, достойный вниманиясостояние потокаимеют:
- Тупик: Тупик (сосредоточиться)
- Выполнение: работает
- Ожидание ресурсов: Ожидание по условию (фокус на)
- Ожидание получения монитора: Ожидание записи монитора (фокус на)
- Приостановлено: Приостановлено
- Ожидание объекта: Object.wait() или TIMED_WAITING
- Блокировка: заблокировано (сосредоточиться)
- Остановка: стоянка
Конкретное значение заключается в следующем:
(a). Deadlock
заблокированная нить, обычно относится к возникновению нескольких вызовов потоков во времяВзаимное занятие ресурсов, что приводит к ситуации, когда ожидание не может быть снято.
(b). Runnable
Обычно означает, что потокстатус выполнения, нить занимаетресурс, являетсяобработать запрос. вероятно, будет проходить
SQLКогда он выполняется в базе данных, можно работать с определенным файлом и выполнять преобразование типа данных.
(c). Waiting on condition
Состояние ожидает потоксостояниеслучилось. Какова конкретная причина, могут быть объединены
stacktraceанализировать. нить в этомсостояние ожидания, как только данные будут готовы для чтения, поток будет повторно активирован для чтения и обработки данных.
Поток ожидает ресурсы или ожидает выполнения определенного условия. Конкретную причину необходимо проанализировать в сочетании со следующей информацией о стеке.
-
еслиинформация о стекеявно дакод приложения, это доказывает, что нитьжду ресурсов. Обычно многопрочитать ресурси ресурс используетблокировка ресурсовслучае, нить входитсостояние ожидания.
-
Если обнаружено, чтомного темнаходятся в этом состоянии, и информация о стеке знает, чтоОжидание сетевого чтения и записи,Это потому чтоперегрузка сетиПривести кПоток не может быть выполнен, скорее всего аузкое место в сетиСимптомы:
- сеть оченьзанятый, почти вся полоса пропускания потребляется, и остается еще много данных, ожидающих чтения и записи сетью;
- сеть может бытьбесплатно, но из-замаршрутизацияилибрандмауэрПо другим причинам посылка не может нормально дойти.
-
Также распространена ситуация, когда нить
sleep,ждатьsleepПришло время пробудиться.
(d). Locked
блокировка потока, относится к ресурсам, необходимым во время выполнения текущего потокадолгое ожиданиеноне удалось получить, определяемый диспетчером потоков контейнера каксостояние блокировки, что можно понимать какТайм-аут ожидания ресурсаразгром.
(e) Ожидание входа в монитор и в Object.wait()
MonitorдаJavaмежду нитямиВзаимное исключение и сотрудничествоосновное средство, его можно рассматривать какобъектилиClassизЗамок. Каждый объект имеетmonitor.
5.1 Пример взаимоблокировки
Ниже приведентупикслучае, вIntLockопределяет два статическихповторная блокировкаэкземпляр, объявленный в основном методедве нитиправильнодва замкаконкурировать за ресурсы.
public class DeadLockRunner {
public static void main(String[] args) {
IntLock r1 = new IntLock(1);
IntLock r2 = new IntLock(2);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
public static class IntLock implements Runnable {
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock();
private int lock;
public IntLock(int lock) {
this.lock = lock;
}
@Override
public void run() {
try {
if (lock == 1) {
lock1.lock();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock2.lock();
} else {
lock2.lock();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock1.lock();
}
} finally {
if (lock1.isHeldByCurrentThread()) {
lock1.unlock();
}
if (lock2.isHeldByCurrentThread()) {
lock2.unlock();
}
}
}
}
}
5.2 Анализ журнала дампа
запускатьDeadLockRunnerизmain()метод, используяjpsПросмотр заблокированjvmпроцессid, затем используйтеjstackПроверятьинформация о стеке потоков, можно обнаружить, что два потока взаимодействуют друг с другомконкурирующие ресурсы,возникает тупик.
$ jstack -l 15584
2018-08-12 20:35:40
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.172-b11 mixed mode):
// 省略...
Found one Java-level deadlock:
=============================
"Thread-1":
waiting for ownable synchronizer 0x000000076ad61180, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-0"
"Thread-0":
waiting for ownable synchronizer 0x000000076ad611b0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076ad61180> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
at io.ostenant.deadlock.DeadLockRunner$IntLock.run(DeadLockRunner.java:47)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076ad611b0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
at io.ostenant.deadlock.DeadLockRunner$IntLock.run(DeadLockRunner.java:37)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
Ссылаться на
Чжоу Чжимин, Глубокое понимание виртуальной машины Java: расширенные функции и лучшие практики JVM, Machinery Industry Press
Добро пожаловать в технический публичный аккаунт: Zero One Technology Stack
Эта учетная запись будет продолжать делиться сухими товарами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.