当前位置 博文首页 > 香菜:《Arthas系列2》 阿里巴巴教你调用exe!so easy,速度收

    香菜:《Arthas系列2》 阿里巴巴教你调用exe!so easy,速度收

    作者:[db:作者] 时间:2021-07-17 09:38

    目录

    点赞再看,养成赞美的习惯,微信搜一搜【香菜聊游戏】关注我。???

    1、如何根据表现查代码

    2、如何实现自己的java 进程列表

    3、一步步实现代码

    4、总结:


    图片

    点赞再看,养成赞美的习惯,微信搜一搜【香菜聊游戏】关注我。???

    ?

    ????今天学习一下Arthas是如何打印出当前机器上的所有Java线程的和调用控制台的,这个技术点不清楚,我们从Arthas的代码中找出实现,学习下知识点,在下次自己用的时候可以有思路,但是Arthas的代码量如此之多,在没人带的情况下怎么读代码呐?

    1、如何根据表现查代码

    1.1 调试断点,因为上篇文章我已经介绍了怎么调试,能调试的代码一定要调试,断电跟踪代码,因此我也想调试的方式去跟踪代码,但是我在打上断点的时候,并且使用命令之后,启动之后发现断点没有生效,思考下为什么没有生效?上期的文章有答案,调试器的原理。

    java?-jar?arthas-boot.jar

    1.2 读代码,既然要读代码了就不能怕读代码,读代码不需要任何的环境,不要任何的测试,不需要任何的条件,只要跟着代码的走向即可。带好小本,记录好自己的理解。

    1.3 举例

    看到打印的日志如下,既然想看他的源码, 从运行的日志打印,分析日志的内容,发现打印的也没有参数,直接拷贝。不要想那么多,直接全局搜索,找到下面的不少用处,我们稍微扫一下就看到了很多地方不是代码调用,我们直接定位到Arthas-boot,OK,我们找到了这个代码的源头,直接进入理解阶段。

    图片

    图片

    2、如何实现自己的java 进程列表

    在跟踪代码代码的过程中,也要理清楚思路,作者到底是怎么做成这件事,如果是你 会有什么样的思路,如果你的思路刚好和作者的不谋而合,我相信你理解起来代码就很简单,如果你的思路和作者的不同,我们应该思考为什么Arthas的作者这么做,你的方案是不是更好,尽信书不如无书!我们带着问题开始吧。

    1、访问环境变量,如何找到jps

    1.1 如何读取电脑的环境变量 :System.getProperty("java.home")

    1.2 jps 是什么?jps 是java提供的一个显示当前所有java进程pid的命令,我们发现了事情的核心。

    1.3 如何找到jps ?jps 的路径可能不同,或者Arthas运行的系统不同,作者直接列出了所有的可能路径,总有一个蒙准。

    private?static?File?findJps() {
    ? ? ? ?// Try to find jps under java.home and System env JAVA_HOME
    ? ? ? ?String?javaHome?=?System.getProperty("java.home");
    ? ? ? ?String[]?paths?=?{?"bin/jps",?"bin/jps.exe",?"../bin/jps",?"../bin/jps.exe"?};
    
    ? ? ? ?List<File>?jpsList?=?new?ArrayList<File>();
    ? ? ? ?for?(String?path?:?paths) {
    ? ? ? ? ? ?File?jpsFile?=?new?File(javaHome,?path);
    ? ? ? ? ? ?if?(jpsFile.exists()) {
    ? ? ? ? ? ? ? ?AnsiLog.debug("Found jps: "?+?jpsFile.getAbsolutePath());
    ? ? ? ? ? ? ? ?jpsList.add(jpsFile);
    ? ? ? ? ? }
    ? ? ? }
    ? ??//省略了不重要的代码
    }

    2、jps命令格式

    问题:jps 命令 的执行格式

    看代码中jps 有两种方式,一种加V ,信息更多,一种不加v 仅仅列出了所有的线程。

    ? String[] command = null;
    ? ? ? if (v) {
    ? ? ? ? ? command = new String[] { jps, "-v", "-l" };
    ? ? ? } else {
    ? ? ? ? ? command = new String[] { jps, "-l" };
    ? ? ? }
    
    ? ? ? List<String> lines = ExecutingCommand.runNative(command);

    3、运行cmd

    我们看到Arthas是在控制台窗口中运行的,我们的问题是:

    3.1 怎么执行命令?使用runtime的exec接口,直接调用系统命令

    3.2 Process 是什么?process是代表一个进程,启动的控制台窗口就是一个Process

    
    
    ??public?static?List<String>?runNative(String[]?cmdToRunWithArgs) {
    ? ? ? ?Process?p?=?null;
    ? ? ? ?try?{
    ? ? ? ? ? ?p?=?Runtime.getRuntime().exec(cmdToRunWithArgs);
    
    

    4、读取输出并编号

    代码所在位置:com.taobao.arthas.common.ExecutingCommand#runNative(java.lang.String[])

    问题:怎么读取控制台窗口的输出,或者说接管控制台窗口,使用process.getInputStream() 获取控制台的输出。

    
    ArrayList<String> sa = new ArrayList<String>();
    ? ? ? BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    ? ? ? try {
    ? ? ? ? ? String line;
    ? ? ? ? ? while ((line = reader.readLine()) != null) {
    ? ? ? ? ? ? ? sa.add(line);
    ? ? ? ? ? }

    3、一步步实现代码

    图片

    1. 核心技术点是调用jps.exe 的命令

    2. 如何执行命令

      jps -l

      ?

    3. 输出控制台输出

      完整代码:

    
    package?com.taobao.arthas.core;
    import?java.io.BufferedReader;
    import?java.io.File;
    import?java.io.IOException;
    import?java.io.InputStreamReader;
    
    /**
    * 获得机器上所有Java线程
    
    * @author 香菜
    */
    public?class?Aain?{
    ? ?public?static?void?main(String[]?args)?throws?IOException?{
    ? ? ? ?//1、获取jps地址,执行完成之后可以看下对应的路径下是否有jps.exe
    ? ? ? ?String?jpsPath?=?getJpsPath();
    ? ? ? ?//2、运行cmd
    ? ? ? ?runCmd(jpsPath);
    
    ? }
    
    ? ?/**
    ? ??* 读取输出
    ? ??* @param reader
    ? ??* @throws IOException
    ? ??*/
    ? ?private?static?void?readOutput(BufferedReader?reader)?throws?IOException?{
    ? ? ? ?try?{
    ? ? ? ? ? ?String?line;
    ? ? ? ? ? ?while?((line?=?reader.readLine())?!=?null) {
    ? ? ? ? ? ? ? ?System.out.println(line);
    ? ? ? ? ? }
    ? ? ? }?catch?(Exception?e) {
    ? ? ? ? ? ?e.printStackTrace();
    ? ? ? }?finally?{
    ? ? ? ? ? ?reader.close();
    ? ? ? }
    ? }
    
    ? ?/**
    ? ??* 运行cmd
    ? ??* @param jpsPath
    ? ??* @throws IOException
    ? ??*/
    ? ?private?static?void?runCmd(String?jpsPath)?throws?IOException?{
    ? ? ? ?String[]?cmdStr?=??new?String[] {?jpsPath,?"-l"?};
    ? ? ? ?Process?p?=?null;
    ? ? ? ?try?{
    ? ? ? ? ? ?p?=?Runtime.getRuntime().exec(cmdStr);
    ? ? ? }?catch?(Exception?e) {
    ? ? ? ? ? ?return;
    ? ? ? }
    ? ? ? ?readOutput(new?BufferedReader(new?InputStreamReader(p.getInputStream())));
    ? }
    
    ? ?/**
    ? ??* 获得jps.exe 的地址
    ? ??* @return
    ? ??*/
    ? ?private?static?String?getJpsPath() {
    ? ? ? ?String?javaHome?=?System.getProperty("java.home");
    ? ? ? ?// 因为在windows环境下演示,只处理window 环境
    ? ? ? ?return?new?File(javaHome,?"../bin/jps.exe").getAbsolutePath();
    ? }
    }

    运行结果:

    图片

    4、总结:

    每个问题的解决,最初的样子都很简单,只是因为加了异常处理,或者特殊需求,或者更全面才成为最终的样子,我们要从复杂的代码中看到技术的本质问题,而不是在大量的代码中迷失。

    今天主要学会了怎么调用控制台,读取控制台输出,以及jps的使用,你都明白了吗?

    推荐阅读??点击标题可跳转

    1、《Arthas系列一》搭建调试环境

    2、用了这些软件,写代码有了飞一般的速度

    3、先学会这些调试技巧,再写代码,效率提高十倍。吐血整理!

    ?

    福利时间

    图片

    cs