1. Введение
Alibaba Arthas — это диагностический инструмент, который позволяет нам отслеживать, профилировать и устранять неполадки в наших приложениях Java. Одно из ключевых преимуществ использования Arthas заключается в том, что нам не нужно изменять наш код или даже перезапускать службы Java, которые мы хотим отслеживать.
В этом руководстве мы начнем с установки Arthas, прежде чем рассмотрим простой пример, чтобы продемонстрировать некоторые ключевые функции Arthas.
Наконец, поскольку Arthas написан на Java, он кроссплатформенный и будет успешно работать в Linux, macOS и Windows.
2. Загрузка и начало работы
Во-первых, давайте начнем с загрузки библиотеки Arthas либо напрямую по ссылке для скачивания , либо с помощью curl
:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
Теперь давайте проверим его работу , запустив Arthas с опцией -h
(help):
java -jar arthas-boot.jar -h
В случае успеха мы должны увидеть справочное руководство для всех отображаемых команд:
3. Тематическое исследование
В этом руководстве мы будем использовать очень простое приложение, основанное на довольно неэффективной реализации последовательности Фибоначчи с использованием рекурсии:
public class FibonacciGenerator {
public static void main(String[] args) {
System.out.println("Press a key to continue");
System.in.read();
for (int i = 0; i < 100; i++) {
long result = fibonacci(i);
System.out.println(format("fib(%d): %d", i, result));
}
}
public static long fibonacci(int n) {
if (n == 0 || n == 1) {
return 1L;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
Наиболее интересной частью этого примера является метод Фибоначчи
, который следует математическому определению Фибоначчи.
В основном
методе мы используем цикл for
с относительно большими числами, поэтому наш компьютер будет занят более длительными вычислениями. Это, конечно, именно то, что мы хотим, чтобы продемонстрировать Артаса.
4. Запуск Артаса
А теперь попробуем Артаса! Первое, что нам нужно сделать, это запустить наше небольшое приложение Фибоначчи. Для этого мы можем использовать нашу любимую IDE или запустить ее прямо в терминале. Он попросит нажать клавишу, чтобы начать. Нажмем любую клавишу после того, как прикрепим процесс к Артасу.
Теперь давайте запустим исполняемый файл Arthas:
java -jar arthas-boot.jar
Артас предлагает меню, чтобы выбрать, к какому процессу мы хотим подключиться:
[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 25500 com.foreach.arthas.FibonacciGenerator
...
Давайте выберем тот, который называется com.foreach.arthas.FibonacciGenerator
. Просто введите номер из списка, в данном примере «1», а затем нажмите Enter.
Теперь Артас подключится к этому процессу и начнет:
INFO] Try to attach process 25500
[INFO] Attach process 25500 success.
...
Как только мы запустим Arthas, у нас появится подсказка, в которой мы можем вводить различные команды.
Мы можем использовать команду справки
, чтобы получить больше информации о доступных опциях. Более того, чтобы облегчить использование Артаса, мы также можем использовать клавишу табуляции для автозаполнения его команд.
После подключения Артаса к нашему процессу теперь мы можем нажать клавишу, и программа начнет печатать числа Фибоначчи.
5. Панель управления
Как только Артас запустится, мы сможем использовать приборную панель. В этом случае мы продолжаем, набрав команду панели инструментов
. Теперь мы видим подробный экран с несколькими панелями и большим количеством информации о нашем Java-процессе:
Рассмотрим некоторые из них более подробно:
- Верхний раздел посвящен потокам, запущенным в данный момент.
- Одним из важных столбцов является потребление ЦП для каждого потока.
- В разделе 3 показано время ЦП на поток.
- Еще одна интересная панель предназначена для анализа памяти. Различные области памяти перечислены со своей статистикой. С правой стороны у нас есть информация о сборщике мусора .
- Наконец, в разделе 5 у нас есть информация о хост-платформе и JVM.
Мы можем выйти из приборной панели, нажав q
.
Мы должны помнить, что Артас будет привязан к нашему процессу, даже если мы выйдем. Итак, чтобы правильно отвязать его от нашего процесса, нам нужно запустить команду остановки
.
**** ``
6. Анализ трассировки стека
В дашборде мы увидели, что наш основной
процесс занимает почти 100% CPU. Этот процесс имеет идентификатор
1, который мы видим в самом первом столбце.
Теперь, когда мы вышли из панели инструментов, мы можем более подробно проанализировать процесс, выполнив команду потока
:
thread 1
Число, переданное в качестве аргумента, является идентификатором потока. Артас выводит трассировку стека, которая, что неудивительно, перегружена вызовами метода Фибоначчи .
Если трассировка стека длинная и утомительная для чтения, команда thread позволяет нам использовать конвейеры:
thread 1 | grep 'main('
Это напечатает только строку, соответствующую команде grep
:
[arthas@25500]$ thread 1 | grep 'main('
at com.foreach.arthas.FibonacciGenerator.main(FibonacciGenerator.java:10)
7. Декомпилировать класс Java
Давайте представим ситуацию, когда мы анализируем Java-приложение, о котором мало или совсем ничего не знаем, и вдруг обнаруживаем, что стек усыпан повторяющимися вызовами типа:
[arthas@59816]$ thread 1
"main" Id=1 RUNNABLE
at app//com.foreach.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
at app//com.foreach.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
...
Поскольку мы запускаем Arthas, мы можем декомпилировать класс, чтобы увидеть его содержимое. Для этого мы можем использовать команду jad
, передав полное имя класса в качестве аргумента:
jad com.foreach.arthas.FibonacciGenerator
ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@799f7e29
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@60f1dd34
Location:
/home/amoreno/work/foreach/tutorials/libraries-3/target/
/*
* Decompiled with CFR.
*/
package com.foreach.arthas;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
public class FibonacciGenerator {
public static void main(String[] arrstring) throws IOException {
Результатом является декомпилированный класс Java и некоторые полезные метаданные, такие как местоположение класса . Это действительно полезная и мощная функция.
8. Класс поиска и метод поиска
Команда search class удобна при поиске классов, загруженных в JVM. Мы можем использовать его, набрав sc
и передав шаблон с подстановочными знаками или без них в качестве аргумента :
[arthas@70099]$ sc *Fibonacci*
com.foreach.arthas.FibonacciGenerator
Affect(row-cnt:1) cost in 5 ms.
Получив полное имя класса, мы можем искать дополнительную информацию, используя два дополнительных флага:
-d
для отображения сведений о классе-f
для отображения полей класса
Однако поля класса необходимо запрашивать вместе с деталями:
[arthas@70099]$ sc -df com.foreach.arthas.FibonacciGenerator
class-info com.foreach.arthas.FibonacciGenerator
...
Точно так же мы можем использовать команду sm
(метод поиска) для поиска загруженных методов в классе. В этом случае для нашего класса com.foreach.arthas.FibonacciGenerator
мы можем запустить:
[arthas@70099]$ sm com.foreach.arthas.FibonacciGenerator
com.foreach.arthas.FibonacciGenerator <init>()V
com.foreach.arthas.FibonacciGenerator main([Ljava/lang/String;)V
com.foreach.arthas.FibonacciGenerator fibonacci(I)J
Affect(row-cnt:3) cost in 4 ms.
Мы могли бы также использовать флаг -d
для получения сведений о методах . Наконец, мы можем передать имя метода в качестве необязательного аргумента, чтобы сократить количество возвращаемых методов:
sm -d com.foreach.arthas.FibonacciGenerator fibonacci
declaring-class com.foreach.arthas.FibonacciGenerator
method-name fibonacci
modifier public,static
annotation
parameters int
return long
exceptions
classLoaderHash 799f7e29
9. Мониторинг вызовов методов
Еще одна крутая вещь, которую мы можем делать с Артасом, — это мониторинг метода. Это может быть очень удобно при отладке проблем с производительностью в наших приложениях. Для этого мы можем использовать команду монитора
.
Для команды монитора
требуется флаг -c <секунды>
и два аргумента — полное имя класса и имя метода.
Для нашего примера давайте теперь вызовем monitor
:
monitor -c 10 com.foreach.arthas.FibonacciGenerator fibonacci
Как и ожидалось, Артас будет печатать метрики о методе Фибоначчи
каждые 10 секунд:
Affect(class-cnt:1 , method-cnt:1) cost in 47 ms.
timestamp class method total success fail avg-rt(ms) fail-rate
-----------------------------------------------------------------------------------------------------------------------------
2020-03-07 11:43:26 com.foreach.arthas.FibonacciGenerator fibonacci 528957 528957 0 0.07 0.00%
...
У нас также есть метрики для тех вызовов, которые заканчиваются сбоями, и они могут быть полезны для отладки.
10. Аргументы метода мониторинга
В случае, если нам нужно отладить параметры метода, мы можем использовать команду watch
. Но синтаксис немного сложнее:
watch com.foreach.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10
Рассмотрим подробно каждый из аргументов:
- Первый аргумент - это имя класса
- Во-вторых, это имя метода.
- Третий аргумент — это выражение OGNL , определяющее, что мы хотим смотреть — в данном случае это первый (и единственный) параметр метода и возвращаемое значение.
- Четвертый и последний необязательный аргумент — это логическое выражение, используемое для фильтрации вызовов, которые мы хотим отслеживать.
В этом примере мы хотим отслеживать аргумент только тогда, когда он больше 10. Наконец, мы добавляем флаг, чтобы ограничить количество результатов до 10:
watch com.foreach.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 19 ms.
ts=2020-02-17 21:48:08; [cost=30.165211ms] result=@ArrayList[
@Integer[11],
@Long[144],
]
ts=2020-02-17 21:48:08; [cost=50.405506ms] result=@ArrayList[
@Integer[12],
@Long[233],
]
...
Здесь мы можем увидеть примеры вызовов с их процессорным временем и входными/возвратными значениями.
11. Профайлер
Очень наглядная возможность для тех, кто интересуется производительностью приложений, доступна через команду профилировщика
. Профилировщик оценит производительность процессора, который используют наши процессы.
Запустим профилировщик, запустив profiler start
. Это неблокирующая задача, то есть мы можем продолжать использовать Arthas, пока работает профайлер.
В любой момент мы можем узнать, сколько сэмплов есть у профилировщика, запустив профайлер getSamples
.
Давайте теперь остановим профилировщик с помощью остановки профилировщика.
На этом этапе сохраняется изображение FlameGraph . Именно в этом случае у нас есть график с преобладающей нитью Фибоначчи :
Обратите внимание, что эта диаграмма может быть особенно полезна, когда мы хотим определить, на что тратится процессорное время.
12. Заключение
В этом уроке мы рассмотрели некоторые из самых мощных и полезных функций Arthas.
Как мы видели, у Arthas есть много команд, которые могут помочь нам диагностировать множество проблем. Это также может быть особенно полезно, когда мы не можем получить доступ к коду исследуемого приложения или если мы хотим провести быструю диагностику проблемного приложения, работающего на сервере.
Как всегда, полный исходный код статьи доступен на GitHub .