当前位置:网站首页>Arthas source code learning-1

Arthas source code learning-1

2022-06-25 15:24:00 Running pig ZC

Previous preparation

1: Source download :https://github.com/alibaba/arthas.git

2: Import to idea, I choose to use it directly idea Download and open

image-20210101140826921

3: Overall directory structure

image-20210101141004000

image-20210101141023095

attach The preparatory work

Find the startup class and debug mode

​ com.taobao.arthas.boot.Bootstrap#main

 // Get some configuration 
 CLI cli = CLIConfigurator.define(Bootstrap.class);

Get a series of annotations on the startup class and the contents inside , Finally, a client is returned

image-20210101142331695

Wrap the client as a command line

  // Wrap the client as a command line 
  CommandLine commandLine = cli.parse(Arrays.asList(args));

take client Inject into the startup class

 CLIConfigurator.inject(commandLine, bootstrap);

Filtering process

pid = ProcessUtils.select(bootstrap.isVerbose(), telnetPortPid, bootstrap.getSelect());

adopt jps The command lists the processes

Map<Long, String> processMap = listProcessByJps(v);

findJps Where is the command

// Get system variables 
String javaHome = System.getProperty("java.home");

obtain jps The order set of , There may be more than one , Return to the first

 if (jpsList.isEmpty()) {
    
            AnsiLog.debug("Can not find jps under :" + javaHome);
            String javaHomeEnv = System.getenv("JAVA_HOME");
            AnsiLog.debug("Try to find jps under env JAVA_HOME :" + javaHomeEnv);
            for (String path : paths) {
    
                File jpsFile = new File(javaHomeEnv, path);
                if (jpsFile.exists()) {
    
                    AnsiLog.debug("Found jps: " + jpsFile.getAbsolutePath());
                    jpsList.add(jpsFile);
                }
            }
        }

return jps The catalog of , Now we know jps Under which directory , It will be implemented later jps command , List all java process

image-20210101144617893

structure jps command , there v It stands for verbose, It's equivalent to what we often do jps -lvm Medium v

image-20210101144820459

perform jps command ,

List<String> lines = ExecutingCommand.runNative(command);

image-20210101145135878

Middle pair jps Format the returned data string

Get PID, Mapping with the corresponding process , Store in a map in

image-20210101145619886

The process number and the corresponding jps line Print on the console , Then block it

  int count = 1;
        for (String process : processMap.values()) {
    
            if (count == 1) {
    
                System.out.println("* [" + count + "]: " + process);
            } else {
    
                System.out.println(" [" + count + "]: " + process);
            }
            count++;
        }

as follows , Next, let's input the corresponding process number , Here select the previously run TestArthasApplication, choice 5

image-20210101145807475

Next, do some parameter verification

 // Parameter checking 
        if (choice <= 0 || choice > processMap.size()) {
    
            return -1;
        } 
............
............

We pressed 5 after , The final choice is PID=12558 , As we expected

image-20210101150542505

Another round of parameter verification ,-- id Check and so on , And will prompt some error messages

  private static void checkTelnetPortPid(Bootstrap bootstrap, long telnetPortPid, long targetPid) {
    
        if (telnetPortPid > 0 && targetPid != telnetPortPid) {
    
            AnsiLog.error("The telnet port {} is used by process {} instead of target process {}, you will connect to an unexpected process.",
                    bootstrap.getTelnetPortOrDefault(), telnetPortPid, targetPid);
            AnsiLog.error("1. Try to restart arthas-boot, select process {}, shutdown it first with running the 'stop' command.",
                            telnetPortPid);
            AnsiLog.error("2. Or try to stop the existing arthas instance: java -jar arthas-client.jar 127.0.0.1 {} -c \"stop\"", bootstrap.getTelnetPortOrDefault());
            AnsiLog.error("3. Or try to use different telnet port, for example: java -jar arthas-boot.jar --telnet-port 9998 --http-port -1");
            System.exit(1);
        }
    }

Get arthas Of home, Then get the source code directory

CodeSource codeSource = Bootstrap.class.getProtectionDomain().getCodeSource();

file:/C:/Users/zhucc/IdeaProjects/arthas/boot/target/classes/

List arthas lib The catalog of , It's mainly about getting arthas edition

 List<String> versionList = listNames(ARTHAS_LIB_DIR);

Get the local version arthas

 String localLastestVersion = null;
            if (!versionList.isEmpty()) {
    
                localLastestVersion = versionList.get(versionList.size() - 1);
            }
            // Get the latest version of arthas, Download tool 
            String remoteLastestVersion = DownloadUtils.readLatestReleaseVersion();
 public static String readLatestReleaseVersion() {
    
        InputStream inputStream = null;
        try {
    
            URLConnection connection = openURLConnection(ARTHAS_LATEST_VERSIONS_URL);
            inputStream = connection.getInputStream();
            return IOUtils.toString(inputStream).trim();
        } catch (Throwable t) {
    
            AnsiLog.error("Can not read arthas version from: " + ARTHAS_LATEST_VERSIONS_URL);
            AnsiLog.debug(t);
        } finally {
    
            IOUtils.close(inputStream);
        }
        return null;
    }

Check whether you want to download

localLastestVersion.compareTo(remoteLastestVersion) < 0

else {
    
                if (remoteLastestVersion != null) {
    
                    if (localLastestVersion.compareTo(remoteLastestVersion) < 0) {
    
                        AnsiLog.info("local lastest version: {}, remote lastest version: {}, try to download from remote.",
                                        localLastestVersion, remoteLastestVersion);
                        needDownload = true;
                    }
                }
            }

image-20210101153721453

Get arthas My feeling path

image-20210101153854174

check process id

   if (telnetPortPid > 0 && pid == telnetPortPid) {
    
            AnsiLog.info("The target process already listen port {}, skip attach.", bootstrap.getTelnetPortOrDefault());
        }

Start class loading

By class url Class loader to load files on disk , get files

image-20210101154614946

To obtain by reflection main Method

Assemble parameters in the command

 if (bootstrap.getCommand() != null) {
    
            telnetArgs.add("-c");
            telnetArgs.add(bootstrap.getCommand());
        }
        if (bootstrap.getBatchFile() != null) {
    
            telnetArgs.add("-f");
            telnetArgs.add(bootstrap.getBatchFile());
        }
        if (bootstrap.getHeight() != null) {
    
            telnetArgs.add("--height");
            telnetArgs.add("" + bootstrap.getHeight());
        }
        if (bootstrap.getWidth() != null) {
    
            telnetArgs.add("--width");
            telnetArgs.add("" + bootstrap.getWidth());
        }

Set a context in the current thread , and invoke just telnetConsole.main Method

image-20210101155237307

stay telnetConsole.main Break point , Has entered

image-20210101155337574

com.taobao.arthas.client.TelnetConsole#process(java.lang.String[], java.awt.event.ActionListener)

call Start the same interface as the class , Set the parameters , wait , No more details here , This is followed by a series of parameter verifications

TelnetConsole telnetConsole = new TelnetConsole();
CLI cli = CLIConfigurator.define(TelnetConsole.class);
CommandLine commandLine = cli.parse(Arrays.asList(args));
CLIConfigurator.inject(commandLine, telnetConsole);

Get a terminal Terminal

final ConsoleReader consoleReader = new ConsoleReader(System.in, System.out);
consoleReader.setHandleUserInterrupt(true);
Terminal terminal = consoleReader.getTerminal();

// support catch ctrl+c event
terminal.disableInterruptCharacter();
if (terminal instanceof UnixTerminal) {
    
    ((UnixTerminal) terminal).disableLitteralNextCharacter();
}

Connecting terminals , After connecting , Return to success – STATUS_OK

org.apache.commons.net.SocketClient#connect(java.lang.String, int)
原网站

版权声明
本文为[Running pig ZC]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202200503403804.html