Java diagnostic tool Arthas-- an artifact that unleashes potential

Hey, are you struggling with debugging and diagnosing issues in Java development?

Don't worry, I'm going to tell you a secret weapon! It's like a superhero who can unleash your potential and solve your troubles! Its name is Arthas, it is a Java diagnostic tool, it is the savior of developers!

It can not only help you monitor and analyze the running status of Java applications in real time, but also allow you to perform online debugging in the production environment. It is like a god! Whether viewing method call stacks, monitoring thread status, or dynamically modifying code, Arthas can handle it with ease!

1 Introduction

Alibaba Arthas is a diagnostic tool that can be used to monitor, analyze and solve problems of Java applications. A major advantage of using Arthas is that we don't need to modify the code or even restart the Java services we want to monitor.

In this tutorial, we will first install Arthas, and after that, demonstrate some key features of Arthas through a simple case.

Finally, since Arthas is written in Java, it is cross-platform and runs on Linux, macOS, and Windows.

2. Download and Getting Started

First, we can download the Arthas library via a direct download link or using curl:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar

Now, let's test that it works by running Arthas with the -h (help) option:

java -jar arthas-boot.jar -h

If successful, we should see the help guide showing all commands:

picture

3. Case study

In this tutorial we'll use a very simple application, based on a relatively inefficient implementation of the Fibonacci sequence implemented using recursion:

public class FibonacciGenerator {

    public static void main(String[] args) {
        System.out.println("按任意键继续");
        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);
        }
    }
}

The most interesting part of this example is the fibonacci method that follows the mathematical definition of the Fibonacci sequence.

In the main method, we use a loop and relatively large numbers in order to let the computer do the calculations for a long time. This is of course exactly what we want in order to demonstrate Arthas.

4. Start Arthas

Let's try Arthas now! The first thing we need to do is run our little Fibonacci application. We can use our favorite IDE or run it directly in the terminal. It will ask to press a key to start. We will press any key after attaching the process to Arthas.

Now, let's run the Arthas executable:

java -jar arthas-boot.jar

Arthas prompts for a process to attach to:

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

Let's select the process named com.baeldung.arthas.FibonacciGenerator. In this example, simply enter the number '1' into the list and press Enter.

Arthas will now attach to the process and start:

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

Once Arthas starts, we have a prompt where we can issue different commands.

We can use the help command to get more information about available options. In order to facilitate the use of Arthas, we can also use the tab key to automatically complete its commands.

With Arthas attached to the process, we can now press a key and the program will start printing Fibonacci numbers.

5. Dashboard

Once Arthas is started, we can use the dashboard. In this case, we use the dashboard by typing the "dashboard" command. We can now see a detailed screen with several panels and lots of information about our Java process:

picture

Let's look at some of these in more detail:

  • The top area is dedicated to displaying currently running threads

  • An important column is the CPU usage per thread

  • The third part shows the CPU time of each thread

  • Another interesting panel is memory analysis. The different memory regions are listed along with their statistics. On the right we have information for the garbage collector

  • Finally, in the fifth section, we have information about the host platform and the JVM

We can exit the dashboard by pressing the "q" key.

We should remember that even after exiting, Arthas will still be attached to our process. Therefore, in order to properly disconnect it from our process, we need to run the "stop" command.

6. Analyzing stack traces

In the dashboard, we see that our main process is using almost 100% of the CPU. The process ID is 1, as you can see in the first column.

Now that we've exited the dashboard, we can analyze the process in more detail by running the "thread" command :

thread 1

The number passed as an argument is the thread ID. Arthas prints a stack trace filled with calls to fibonacci methods.

If the stack trace is long and hard to read, you can use the "thread" command combined with the "grep" command to filter it:

thread 1 | grep 'main('

This will only print lines that match the "grep" command:

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

7. Decompile Java classes

Suppose we are analyzing a Java application about which we know little or nothing, and suddenly find that the stack is filled with repeated calls of the following types:

[arthas@59816]$ 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)
  ...

Since we ran Arthas, we can decompile a class to see its contents. To achieve this, we can use the jad command, passing the qualified class name as an argument:

jad com.baeldung.arthas.FibonacciGenerator

类加载器:
+-jdk.internal.loader.ClassLoaders $ AppClassLoader @ 799f7e29
  +-jdk.internal.loader.ClassLoaders $ PlatformClassLoader @ 60f1dd34

位置:
/home/amoreno/work/baeldung/tutorials/libraries-3/target/
/*
 * 反编译使用CFR。
 */
package com.baeldung.arthas;

import java.io.IOException;
import java.io.InputStream;
importjava.io.PrintStream;

public class FibonacciGenerator {
    public static void main(String[] arrstring) throws IOException {

The output is the decompiled Java class and some useful metadata like the location of the class. This is a very useful and powerful feature.

8. Search class and search method

The Search Classes command is very handy when searching for classes loaded in the JVM. We can use this by typing sc and passing the pattern as an argument, with or without wildcards:

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

Once we have the qualified name of a class, we can use two additional flags to find more information:

  • -d show class details

  • -f show the fields of the class

However, the fields of the class must be queried with the details:

[arthas@70099]$ sc -df com.baeldung.arthas.FibonacciGenerator
  class-info        com.baeldung.arthas.FibonacciGenerator
  ...

Similarly, we can use the sm (search method) command to find methods loaded in a class. In this case, for our class com.baeldung.arthas.FibonacciGenerator, we can run:

[arthas@70099]$ 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.

We can use the -d flag to retrieve method details. Finally, we can pass the name of the method as an optional parameter to narrow down the number of returned methods:

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. Monitoring method calls

We can use Arthas to monitor methods, which is very handy when debugging performance issues of the application. For this, we can use the monitor command.

The monitor command takes a -c <seconds> flag and two arguments - qualified class name and method name.

For our case study, let's call monitor:

monitor -c 10 com.baeldung.arthas.FibonacciGenerator fibonacci

As we expected, Arthas will print metrics about the fibonacci method every 10 seconds:

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%
...                                                                           

We also have metrics for those calls that eventually fail - this is useful for debugging.

10. Monitoring Method Parameters

If we need to debug the parameters of the method, we can use the watch command. However, the syntax is slightly more complicated:

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

Let's look at each parameter in detail:

  • The first parameter is the class name

  • The second parameter is the method name

  • The third parameter is an OGNL expression that defines what we want to look at - in this case it's the first (and only) method parameter and return value

  • The fourth and last optional parameter is a boolean expression to filter the calls we want to monitor

For this example, we only want to watch when the parameter is greater than 10. Finally, we add a flag to limit the results to 10:

watch com.baeldung.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10
按Q或Ctrl+C中断。
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],
]
...

Here we can see an example of a call with CPU time and input/return values.

11. Analyzer

For those interested in application performance, a very intuitive capability is provided through the profiler command. The profiler will evaluate the performance of the CPU our process is using.

Let's start the profiler by running profiler start. This is a non-blocking task, meaning we can keep using Arthas while the profiler is working.

At any time you can ask the profiler how many samples it has by running profiler getSamples .

Now let's stop the profiler using profiler stop. At this point, a FlameGraph image will be saved. In this specific case we have a chart dominated by Fibonacci threads:

picture

Note that this graph is especially useful when we want to detect where our CPU time is being spent.

12. Summary

In this tutorial, we explored some of the most powerful and useful features of Arthas.

As we have seen, Arthas has many commands that can help us diagnose various problems. It can also be especially helpful when we don't have access to the code of the application we're reviewing, or if we want to quickly diagnose a problematic application running on a server.

References:

  1. Official documentation: https://arthas.aliyun.com/doc/

  2. Arthas GitHub warehouse address: https://github.com/alibaba/arthas

Guess you like

Origin blog.csdn.net/m0_37723088/article/details/131910975