«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

Arthas предлагает меню для выбора процесса, к которому мы хотим подключиться:

[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 25500 com.baeldung.arthas.FibonacciGenerator
...

Давайте выберем процесс с именем com.baeldung.arthas. Генератор Фибоначчи. Просто введите номер из списка, в этом примере «1», а затем нажмите Enter.

Теперь Артас подключится к этому процессу и запустится:

INFO] Try to attach process 25500
[INFO] Attach process 25500 success.
...                     

Как только мы запустим Артас, у нас появится подсказка, в которой мы можем вводить различные команды.

Мы можем использовать команду help, чтобы получить больше информации о доступных опциях. Более того, чтобы облегчить использование Артаса, мы также можем использовать клавишу табуляции для автозаполнения его команд.

После подключения Артаса к нашему процессу теперь мы можем нажать клавишу, и программа начнет печатать числа Фибоначчи.

5. Информационная панель

После запуска Arthas мы можем использовать панель инструментов. В этом случае мы продолжаем, набрав команду панели инструментов. Теперь мы видим подробный экран с несколькими панелями и большим количеством информации о нашем процессе Java:

Давайте рассмотрим некоторые из них более подробно:

  1. The top section is dedicated to the threads currently running
  2. One of the important columns is the CPU consumption for each thread
  3. Section 3 shows the CPU time per thread
  4. Another interesting pane is for memory analysis. Different memory regions are listed with their statistics. On the right-hand side, we have information about the Garbage Collector
  5. Finally, in section 5 we have information about the host platform and JVM

Мы можем выйти из панели инструментов, нажав q.

Мы должны помнить, что Артас будет присоединен к нашему процессу, даже если мы выйдем. Поэтому, чтобы правильно отвязать его от нашего процесса, нам нужно запустить команду остановки.

6. Анализ трассировки стека

В дашборде мы увидели, что наш основной процесс занимает почти 100% процессорного времени. Этот процесс имеет идентификатор 1, который мы видим в самом первом столбце.

Теперь, когда мы вышли из информационной панели, мы можем более подробно проанализировать процесс, запустив команду потока:

thread 1

Число, переданное в качестве аргумента, является идентификатором потока. Артас выводит трассировку стека, которая, что неудивительно, перегружена вызовами метода Фибоначчи.

Если трассировка стека длинная и утомительная для чтения, команда thread позволяет нам использовать конвейеры:

thread 1 | grep 'main('

Будет напечатана только строка, соответствующая команде grep:

[[email protected]]$ thread 1 | grep 'main('
    at com.baeldung.arthas.FibonacciGenerator.main(FibonacciGenerator.java:10)

7. Декомпилируйте Класс Java

Давайте представим сценарий, в котором мы анализируем Java-приложение, о котором мало или совсем ничего не знаем, и вдруг обнаруживаем, что стек усыпан повторяющимися вызовами типа:

[[email protected]]$ thread 1
"main" Id=1 RUNNABLE
  at app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
  at app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
  ...

Поскольку мы запустив Arthas, мы могли бы декомпилировать класс, чтобы увидеть его содержимое. Для этого мы можем использовать команду jad, передав полное имя класса в качестве аргумента:

jad com.baeldung.arthas.FibonacciGenerator

ClassLoader:
[email protected]
  [email protected]

Location:
/home/amoreno/work/baeldung/tutorials/libraries-3/target/
/*
 * Decompiled with CFR.
 */
package com.baeldung.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. Класс поиска и метод поиска

[[email protected]]$ sc *Fibonacci*
com.baeldung.arthas.FibonacciGenerator
Affect(row-cnt:1) cost in 5 ms.

Команда search class удобна при поиске классов, загруженных в JVM. Мы можем использовать его, набрав sc и передав шаблон с подстановочными знаками или без них в качестве аргумента:


    Получив полное имя класса, мы можем искать дополнительную информацию, используя два дополнительных флага: ~ ~~ -d для отображения сведений о классе -f для отображения полей класса

Однако поля класса должны быть запрошены вместе с деталями:

[[email protected]]$ sc -df com.baeldung.arthas.FibonacciGenerator
  class-info        com.baeldung.arthas.FibonacciGenerator
  ...

Аналогично, мы можем использовать команда sm (метод поиска) для поиска загруженных методов в классе. В этом случае для нашего класса com.baeldung.arthas.FibonacciGenerator мы можем запустить:

[[email protected]]$ sm com.baeldung.arthas.FibonacciGenerator
com.baeldung.arthas.FibonacciGenerator <init>()V
com.baeldung.arthas.FibonacciGenerator main([Ljava/lang/String;)V
com.baeldung.arthas.FibonacciGenerator fibonacci(I)J
Affect(row-cnt:3) cost in 4 ms.

Мы могли бы также использовать флаг -d для получения сведений о методах. Наконец, мы можем передать имя метода в качестве необязательного аргумента, чтобы сузить количество возвращаемых методов:

sm -d com.baeldung.arthas.FibonacciGenerator fibonacci
 declaring-class  com.baeldung.arthas.FibonacciGenerator
 method-name      fibonacci
 modifier         public,static
 annotation
 parameters       int
 return           long
 exceptions
 classLoaderHash  799f7e29

9. Мониторинг вызовов методов

Еще одна интересная вещь, которую мы можем сделать с Arthas, — это отслеживать метод. Это может быть очень удобно при отладке проблем с производительностью в наших приложениях. Для этого мы можем использовать команду монитора.

Для команды monitor требуется флаг -c \u003cсекунды\u003e и два аргумента — полное имя класса и имя метода.

Для нашего примера давайте теперь вызовем монитор:

monitor -c 10 com.baeldung.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.baeldung.arthas.FibonacciGenerator  fibonacci  528957  528957   0     0.07        0.00%
...                                                                           

У нас также есть метрики для тех вызовов, которые заканчиваются в сбоях — и они могут быть полезны для отладки.


10. Аргументы метода мониторинга

В случае, если нам нужно отладить параметры метода, мы можем использовать команду watch. Но синтаксис немного сложнее:

watch com.baeldung.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10

Давайте подробно рассмотрим каждый из аргументов:

    Первый аргумент — это имя класса Второй — имя метода Третий аргумент — OGNL выражение, определяющее, что мы хотим наблюдать — в данном случае это первый (и единственный) параметр метода и возвращаемое значение. Четвертый и последний необязательный аргумент — это логическое выражение, используемое для фильтрации вызовов, которые мы хотим отслеживать

В этом примере мы хотим отслеживать аргумент только тогда, когда он больше 10. Наконец, мы добавляем флаг, чтобы ограничить количество результатов до 10:

watch com.baeldung.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] [email protected][
    @Integer[11],
    @Long[144],
]
ts=2020-02-17 21:48:08; [cost=50.405506ms] [email protected][
    @Integer[12],
    @Long[233],
]
...

Здесь мы можем увидеть примеры вызовов с их процессорным временем и входные/возвратные значения.

11. Profiler

Очень наглядная возможность для тех, кто интересуется производительностью приложений, доступна через команду profiler. Профилировщик оценит производительность процессора, который используют наши процессы.

Запустим профайлер, запустив профайлер start. Это неблокирующая задача, то есть мы можем продолжать использовать Arthas, пока работает профайлер.

В любой момент мы можем узнать, сколько сэмплов есть у профилировщика, запустив профайлер getSamples.

Теперь остановим профилировщик с помощью команды profiler stop. На этом этапе сохраняется изображение FlameGraph. В этом конкретном случае у нас есть диаграмма с преобладающей нитью Фибоначчи:


Обратите внимание, что эта диаграмма может быть особенно полезна, когда мы хотим определить, на что тратится время нашего процессора.

12. Заключение

В этом уроке мы рассмотрели некоторые из самых мощных и полезных функций Arthas.

Как мы видели, у Артаса есть много команд, которые могут помочь нам диагностировать различные проблемы. Это также может быть особенно полезно, когда мы не можем получить доступ к коду исследуемого приложения или если мы хотим провести быструю диагностику проблемного приложения, работающего на сервере.

Как всегда, полный исходный код статьи доступен на GitHub.