ArthasArthas Command处理流程

Posted 九师兄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArthasArthas Command处理流程相关的知识,希望对你有一定的参考价值。

1.概述

转载:Arthas Command处理流程

2.开篇

这篇文章主要是为了分析Arthas的命令的执行过程,整体过程包括任务的创建和任务的执行。

arthas的命令都是实现统一的接口,对外通过process方法进行调用。

public abstract class AnnotatedCommand 
    // 不同的命令又不同的process实现
    public abstract void process(CommandProcess process);


├── AbstractTraceAdviceListener.java
├── DashboardCommand.java
├── DashboardInterruptHandler.java
├── EnhancerCommand.java
├── GroovyAdviceListener.java
├── GroovyScriptCommand.java
├── HeapDumpCommand.java
├── JvmCommand.java
├── MBeanCommand.java
├── MonitorAdviceListener.java
├── MonitorCommand.java
├── MonitorData.java
├── PathTraceAdviceListener.java
├── PerfCounterCommand.java
├── ProfilerCommand.java
├── StackAdviceListener.java
├── StackCommand.java
├── ThreadCommand.java
├── ThreadSampler.java
├── TimeFragment.java
├── TimeTunnelAdviceListener.java
├── TimeTunnelCommand.java
├── TimeTunnelTable.java
├── TraceAdviceListener.java
├── TraceCommand.java
├── TraceEntity.java
├── WatchAdviceListener.java
└── WatchCommand.java

3.任务创建和执行

public class ShellLineHandler implements Handler<String> 

    private ShellImpl shell;
    private Term term;

    @Override
    public void handle(String line) 

        List<CliToken> tokens = CliTokens.tokenize(line);

        // 解析参数生成tokens,根据tokens来创建Job
        Job job = createJob(tokens);
        if (job != null) 
            // 执行任务
            job.run();
        
    

    // 根据请求参数创建任务
    private Job createJob(List<CliToken> tokens) 
        Job job;
        try 
            job = shell.createJob(tokens);
         catch (Exception e) 
            // 省略无关代码
        
        return job;
    

createJob根据传入参数创建Job对象
通过job.run()来执行Job任务
sc *命令,那么根据sc关键字创建SearchClassCommand的任务并执行

4.任务创建流程

public class ShellImpl implements Shell 

    private JobControllerImpl jobController;

    public synchronized Job createJob(List<CliToken> args) 
        Job job = jobController.createJob(commandManager, args, session, new ShellJobHandler(this), term, null);
        return job;
    


public class GlobalJobControllerImpl extends JobControllerImpl 

    public Job createJob(InternalCommandManager commandManager, List<CliToken> tokens, Session session, JobListener jobHandler, Term term, ResultDistributor resultDistributor) 

        final Job job = super.createJob(commandManager, tokens, session, jobHandler, term, resultDistributor);

        JobTimeoutTask jobTimeoutTask = new JobTimeoutTask(job);
        long jobTimeoutInSecond = getJobTimeoutInSecond();
        Date timeoutDate = new Date(System.currentTimeMillis() + (jobTimeoutInSecond * 1000));
        ArthasBootstrap.getInstance().getScheduledExecutorService().schedule(jobTimeoutTask, jobTimeoutInSecond, TimeUnit.SECONDS);
        jobTimeoutTaskMap.put(job.id(), jobTimeoutTask);
        job.setTimeoutDate(timeoutDate);

        return job;
    


public class JobControllerImpl implements JobController 

    public Job createJob(InternalCommandManager commandManager, List<CliToken> tokens, Session session, JobListener jobHandler, Term term, ResultDistributor resultDistributor) 
        checkPermission(session, tokens.get(0));
        int jobId = idGenerator.incrementAndGet();
        StringBuilder line = new StringBuilder();
        for (CliToken arg : tokens) 
            line.append(arg.raw());
        
        boolean runInBackground = runInBackground(tokens);
        // 根据tokens创建Process对象
        Process process = createProcess(session, tokens, commandManager, jobId, term, resultDistributor);
        process.setJobId(jobId);
        // 创建JobImpl包含Process对象
        JobImpl job = new JobImpl(jobId, this, process, line.toString(), runInBackground, session, jobHandler);
        jobs.put(jobId, job);
        return job;
    

createProcess创建tokens对应的Process对象
JobImpl将创建的Process对象进行封装,Job的执行会调用Process的方法

public class JobControllerImpl implements JobController 

    private Process createProcess(Session session, List<CliToken> line, InternalCommandManager commandManager, int jobId, Term term, ResultDistributor resultDistributor) 
        try 
            ListIterator<CliToken> tokens = line.listIterator();
            while (tokens.hasNext()) 
                CliToken token = tokens.next();
                if (token.isText()) 
                    // check before create process
                    checkPermission(session, token);
                    // 1、获取命令对应的处理函数对象Command
                    Command command = commandManager.getCommand(token.value());
                    if (command != null) 
                        // 2、创建Process对象
                        return createCommandProcess(command, tokens, jobId, term, resultDistributor);
                     else 
                        throw new IllegalArgumentException(token.value() + ": command not found");
                    
                
            
            throw new IllegalArgumentException();
         catch (Exception e) 
        
    


    private Process createCommandProcess(Command command, ListIterator<CliToken> tokens, int jobId, Term term, ResultDistributor resultDistributor) throws IOException 
        // 省略相关代码

        ProcessImpl process = new ProcessImpl(command, remaining, command.processHandler(), ProcessOutput, resultDistributor);
        process.setTty(term);
        return process;
    


public class InternalCommandManager 

    private final List<CommandResolver> resolvers;

    public InternalCommandManager(List<CommandResolver> resolvers) 
        this.resolvers = resolvers;
    

    public Command getCommand(String commandName) 
        Command command = null;
        for (CommandResolver resolver : resolvers) 
            // 内建命令在ShellLineHandler里提前处理了,所以这里不需要再查找内建命令
            if (resolver instanceof BuiltinCommandPack) 
                command = getCommand(resolver, commandName);
                if (command != null) 
                    break;
                
            
        
        return command;
    

    private static Command getCommand(CommandResolver commandResolver, String name) 
        List<Command> commands = commandResolver.commands();
        for (Command command : commands) 
            if (name.equals(command.name())) 
                return command;
            
        
    

根据命令的tokens去查询commands获取对应的command创建Process对象。
查询返回的command是AnnotatedCommandImpl对象。

public class BuiltinCommandPack implements CommandResolver 

    private static List<Command> commands = new ArrayList<Command>();

    static 
        initCommands();
    

    @Override
    public List<Command> commands() 
        return commands;
    

    private static void initCommands() 
        commands.add(Command.create(HelpCommand.class));
        commands.add(Command.create(AuthCommand.class));
        commands.add(Command.create(KeymapCommand.class));
        commands.add(Command.create(SearchClassCommand.class));
        commands.add(Command.create(SearchMethodCommand.class));
        commands.add(Command.create(ClassLoaderCommand.class));
        commands.add(Command.create(JadCommand.class));
        commands.add(Command.create(GetStaticCommand.class));
        commands.add(Command.create(MonitorCommand.class));
        commands.add(Command.create(StackCommand.class));
        commands.add(Command.create(ThreadCommand.class));
        commands.add(Command.create(TraceCommand.class));
        commands.add(Command.create(WatchCommand.class));
        commands.add(Command.create(TimeTunnelCommand.class));
        commands.add(Command.create(JvmCommand.class));
        commands.add(Command.create(PerfCounterCommand.class));
        // commands.add(Command.create(GroovyScriptCommand.class));
        commands.add(Command.create(OgnlCommand.class));
        commands.add(Command.create(MemoryCompilerCommand.class));
        commands.add(Command.create(RedefineCommand.class));
        commands.add(Command.create(RetransformCommand.class));
        commands.add(Command.create(DashboardCommand.class));
        commands.add(Command.create(DumpClassCommand.class));
        commands.add(Command.create(HeapDumpCommand.class));
        commands.add(Command.create(JulyCommand.class));
        commands.add(Command.create(ThanksCommand.class));
        commands.add(Command.create(OptionsCommand.class));
        commands.add(Command.create(ClsCommand.class));
        commands.add(Command.create(ResetCommand.class));
        commands.add(Command.create(VersionCommand.class));
        commands.add(Command.create(SessionCommand.class));
        commands.add(Command.create(SystemPropertyCommand.class));
        commands.add(Command.create(SystemEnvCommand.class));
        commands.add(Command.create(VMOptionCommand.class));
        commands.add(Command.create(LoggerCommand.class));
        commands.add(Command.create(HistoryCommand.class));
        commands.add(Command.create(CatCommand.class));
        commands.add(Command.create(Base64Command.class));
        commands.add(Command.create(EchoCommand.class));
        commands.add(Command.create(PwdCommand.class));
        commands.add(Command.create(MBeanCommand.class));
        commands.add(Command.create(GrepCommand.class));
        commands.add(Command.create(TeeCommand.class));
        commands.add(Command.create(ProfilerCommand.class));
        commands.add(Command.create(ShutdownCommand.class));
        commands.add(Command.create(StopCommand.class));
    


public abstract class Command 

    public static Command create(final Class<? extends AnnotatedCommand> clazz) 
        return new AnnotatedCommandImpl(clazz);
    



public class AnnotatedCommandImpl extends Command 

    private CLI cli;
    private Class<? extends AnnotatedCommand> clazz;
    private Handler<CommandProcess> processHandler <

以上是关于ArthasArthas Command处理流程的主要内容,如果未能解决你的问题,请参考以下文章

ArthasArthas使用watch命令(生产上查看方法出入参)

ArthasArthas使用watch命令(生产上查看方法出入参)

arthasArthas 查看 Mbean 的信息

ArthasArthas classloader类加载器

ArthasArthas thread查看线程信息

ArthasArthas retransform动态重新加载类