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

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

今天学习一下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、一步步实现代码


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


如何执行命令


jps -l


输出控制台输出


完整代码:


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的使用,你都明白了吗?

目录
相关文章
|
5月前
|
安全 编译器 API
程序与技术分享:C#调用DLL的几种方法
程序与技术分享:C#调用DLL的几种方法
79 0
|
6月前
|
SQL 分布式计算 前端开发
2024年最全用python写一个自动生成春联的软件,打包exe,2024年最新阿里p8面试题和答案
2024年最全用python写一个自动生成春联的软件,打包exe,2024年最新阿里p8面试题和答案
2024年最全用python写一个自动生成春联的软件,打包exe,2024年最新阿里p8面试题和答案
|
6月前
|
Java 编译器 Go
百度搜索:蓝易云【Go的执行原理以及Go的命令】
这些命令为Go开发者提供了便利的开发、编译、运行、测试和文档查阅等功能,使得Go语言在开发过程中更加高效和便捷。
61 1
|
12月前
《QT从基础到进阶·二十八》QProcess使用,从一个exe程序启动另一个exe程序
《QT从基础到进阶·二十八》QProcess使用,从一个exe程序启动另一个exe程序
346 0
|
小程序 Python
python调用win32api 拉起wps问题排查解决方案
python调用win32api 拉起wps问题排查解决方案
308 0
调试实战 —— dll 加载失败之 Debug Release 争锋篇
调试实战 —— dll 加载失败之 Debug Release 争锋篇
|
Arthas Java 测试技术
Arthas可以对线上jar中的代码进行断点查看
Arthas可以对线上jar中的代码进行断点查看
3127 1
|
Linux 测试技术 网络安全
嘿,Go开发时我是如何远程调试的
嘿,Go开发时我是如何远程调试的
1409 0
嘿,Go开发时我是如何远程调试的
小工具随手记:使用auto-py-to-exe将Python程序打包成exe
小工具随手记:使用auto-py-to-exe将Python程序打包成exe
小工具随手记:使用auto-py-to-exe将Python程序打包成exe
|
C++
安利一个通过命令行使用 VS Code 打开项目的方法
安利一个通过命令行使用 VS Code 打开项目的方法
786 0
安利一个通过命令行使用 VS Code 打开项目的方法