# 远程类更新

首先感谢 Alibaba 开源的 Java 诊断工具 Arthas,提供了核心功能。arthas yyds

然后,这是基于个人工作流,设计的一个用于减少更新远程代码所耗费的时间的功能。目前在功能实现上还有许多不足,交互操作、信息提示也是自己琢磨的,操作起来如果觉得别扭,欢迎通过 Github 提供宝贵意见。

# 使用场景

  1. 平时远程服务器代码调试,Java 代码需要加日志或者修改部分代码时

# 外部工具

远程类更新是借助阿里的 Arthas 工具完成的,实际使用之前,可以通过插件的上传按钮,将工具包上传到服务器的 /tmp/EasyDeploy 目录。

# 使用方法

远程类更新的入口在编辑器的右击菜单中,该功能只支持对 Java 文件操作。在右击菜单中选择 Remote Class Retransform ,会跳出一个操作窗口。

upload-settings.jpg

每个项目在初次使用的时候,会跳出一个选择目标服务器的窗口,先选择一个服务器。选择服务器之后,会进行服务器的连接,然后进行以下操作

  1. 检查服务器连接是否可用
  2. 服务器信息正确的情况下,获取当前服务器的 Java 程序
  3. 检查服务器是否有 Arthas 工具包,如果没有,可以通过窗口的上传按钮进行上传。
  4. upload-settings.jpg

在前面三步准备完成的情况下,会要求选择一个远程 Java 程序进行端口绑定,这个端口是用来和 Arthas 交互的。如果选中的程序没有和端口进行绑定,则端口旁边的图标会呈断开状态,可以点击 Attach Process 按钮进行绑定。

upload-settings.jpg

经过上面的步骤之后,Arthas 已经和远程目标程序绑定了,之后可以点击 Retransform 按钮进行类更新。类更新的步骤分为

  1. 编译本地代码(目前还没发现怎么编译单个文件)
  2. 编译完成后,上传对应的 class 文件到远程服务器
  3. 通过 Arthas 交互端口,向 Arthas 发送 retransform 指令
upload-settings.jpg

成功后会有气泡信息提示。

# 功能限制

正如开头所说,这是借助 Arthas 的 retransform 命令完成的,所以有必要知道什么情况下不适合使用。

  • 不允许新增加 field/method
  • 正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效
public class MathGame {
    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        while (true) {
            game.run();
            TimeUnit.SECONDS.sleep(1);
            // 这个不生效,因为代码一直跑在 while里
            System.out.println("in loop");
        }
    }

    public void run() throws InterruptedException {
        // 这个生效,因为run()函数每次都可以完整结束
        System.out.println("call run()");
        try {
            int number = random.nextInt();
            List<Integer> primeFactors = primeFactors(number);
            print(number, primeFactors);

        } catch (Exception e) {
            System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 可能遇到的问题

下面的问题是我使用过程中遇到且暂时没有解决头绪的问题

  1. 第一次更新的时候,编译失败,报了很多奇怪的错误?

    可以先自己将整个项目编译一遍,比如使用侧边栏 maven 的 compile 功能,编译完后续应该就不会报错了。之前我遇到的时候,编译一遍就没再出现了

    upload-settings.jpg
upload-settings.jpg