当前位置 : 主页 > 编程语言 > java >

漫画:Java如何实现热更新?

来源:互联网 收集:自由互联 发布时间:2022-06-22
Arthas(阿尔萨斯)是 Alibaba 开源的一款 Java 诊断工具,使用它我们可以监控和排查 Java 程序,然而它还提供了非常实用的 Java 热更新功能。 所谓的 Java 热更新是指在不重启项目的情况下

漫画:Java如何实现热更新?_热更新漫画:Java如何实现热更新?_热更新_02漫画:Java如何实现热更新?_java_03漫画:Java如何实现热更新?_java_04漫画:Java如何实现热更新?_Java_05漫画:Java如何实现热更新?_Java_06

Arthas(阿尔萨斯)是 Alibaba 开源的一款 Java 诊断工具,使用它我们可以监控和排查 Java 程序,然而它还提供了非常实用的 Java 热更新功能。

所谓的 Java 热更新是指在不重启项目的情况下实现代码的更新与替换。使用它可以实现不停机更新 Java 程序,尤其是对那些启动非常耗时的 Java 项目来说,更是效果显著。

Arthas 的使用其实非常简单,它为我们提供了一个 Jar 包,我们只需要把这个 Jar 下载到本地,然后运行这个 Jar 包就可以正常使用它的功能了。

Arthas 功能简述

当你遇到以下类似问题而束手无策时,Arthas 可以帮助你解决(来自官方):

  • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  • 是否有一个全局视角来查看系统的运行状况?
  • 有什么办法可以监控到JVM的实时运行状态?
  • 怎么快速定位应用的热点,生成火焰图?
  • Arthas 支持 JDK 6+,支持 Linux/Mac/Winodws,它采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

    Arthas 使用

    Arthas 的使用步骤如下。

    步骤一:下载 Arthas

    首先,我们先把 Arthas 的 Jar 包下载到本地,它的下载地址是:alibaba.github.io/arthas/arth…

    步骤二:启动 Arthas

    我们只需要使用普通的 jar 包启动命令:​​java -jar arthas-boot.jar​​ 来启动 Arthas 即可,启动成功之后的运行界面如下:

    漫画:Java如何实现热更新?_Java_07

    如上图所示则表示 Arthas 启动成功。


    小贴士:当我们运行 java -jar arthas-boot.jar 命令时,首先需要先切换目录至该 jar 包的位置,才能正常的启动 Arthas。


    步骤三:运行 Arthas

    当我们启动完 Arthas 之后,根据上图的提示,我们需要选择一个要调试的 Java 进程,例如我们输入“4”来监测我自己写的一个 Java 测试程序,执行结果如下:

    漫画:Java如何实现热更新?_Java_08

    当出现 Arthas 的 logo 之后,表示 Arthas 正常加载了 Java 进程。

    步骤四:操作 Arthas

    当 Arthas 加载 Java 进程成功之后,我们就可以输入相关的命令来查看相关的信息了。

    假如我们把本地环境视为生产服务器,我们此时需要查看某个运行的 Java 程序是否为最新版的。

    在没有 Arthas 之前,我们通常的步骤是这样的:

  • 找到相应的 jar 包(或者 war 包);
  • 将 jar 包(或者 war 包)下载到本地;
  • 找出相应的类进行解压操作;
  • 然后将解压的 class 文件拖拽到 Java 编译器(Idea 或 Eclipse)中,查看是否为最新的代码。
  • 但如果使用的是 Arthas,那么我们就可以直接通过反编译命令,将字节码编译为正常的 Java 代码,然后再确认是否为最新的代码即可。我们只需要执行 ​​jad​​ 命令即可,实现示例如下:

    漫画:Java如何实现热更新?_Java_09

    这样我们就可以直接来查看这个发布的程序是否为最新版本了。

    不仅如此,我们还可以使用 Arthas 来监测整个程序的运行情况,如下图所示:

    漫画:Java如何实现热更新?_jar_10

    我们还可以用 Arthas 来查看一些 JVM 的相关信息,如下图所示:

    漫画:Java如何实现热更新?_热更新_11

    更多 Arthas 的功能请访问:alibaba.github.io/arthas/comm…

    热更新 Java 代码

    漫画:Java如何实现热更新?_java_12漫画:Java如何实现热更新?_Java_13

    假如我们原来的代码是这样的:

    package com.example;

    import java.util.concurrent.TimeUnit;

    public class App {
    public static void main(String[] args) throws InterruptedException {
    while (true) { // 每两秒钟打印一条信息
    TimeUnit.SECONDS.sleep(3);
    sayHi();
    }
    }

    private static void sayHi() {
    // 需要修改的标识
    boolean flag = true;
    if (flag) {
    System.out.println("Hello,Java.");
    } else {
    System.out.println("Hello,Java中文社群.");
    }
    }
    }

    我们现在想要把 ​​flag​​​ 变量改为 ​​false​​ 就可以这样来做:

  • 使用 Arthas 的内存编译工具将新的 Java 代码编译为字节码;
  • 使用 Arthas 的​​redefine​​ 命令实现热更新。
  • 1.编译字节码

    首先,我们需要将新的 Java 代码编译为字节码,我们可以通过 Arthas 提供的 ​​mc​​​ 命令实现,​​mc​​ 是 Memory Compiler(内存编译器)的缩写。

    实现示例如下:

    [arthas@3478]$ mc /Users/admin/Desktop/App.java -d /Users/admin/Desktop
    Memory compiler output:
    /Users/admin/Desktop/com/example/App.class
    Affect(row-cnt:1) cost in 390 ms.

    其中 ​​-d​​ 表示编译文件的存放位置。


    小贴士:我们也可以使用 javac App.java 生成的字节码,它与此步骤执行的结果相同。


    2.执行热更新

    有了字节码文件之后,我们就可以使用 ​​redefine​​ 命令来实现热更新了,实现示例如下:

    [arthas@51787]$ redefine /Users/admin/Desktop/com/example/App.class
    redefine success, size: 1

    从上述结果可以看出,热更新执行成功,此时我们去控制台查看执行结果,如下图所示:

    漫画:Java如何实现热更新?_热更新_14

    这说明热更新执行确实成功了。

    Arthas 热更新注意事项

    使用热更新功能有一些条件限制,我们只能用它来修改方法内部的一些业务代码,如果我们出现了以下任意一种情况,那么热更新就会执行失败:

  • 增加类属性(类字段);
  • 增加或删除方法;
  • 替换正在运行的方法。
  • 最后一条我们需要单独说明一下,假如我们把上面的示例改为如下代码:

    package com.example;

    import java.util.concurrent.TimeUnit;

    public class App {
    public static void main(String[] args) throws InterruptedException {
    while (true) { // 每两秒钟打印一条信息
    TimeUnit.SECONDS.sleep(3);
    boolean flag = true;
    if (flag) {
    System.out.println("Hello,Java.");
    } else {
    System.out.println("Hello,Java中文社群.");
    }
    }
    }
    }

    那么此时我们再进行热更新操作修改 ​​flag​​​ 的值,那么就会执行失败,因为我们替换的是正在运行中的方法,而我们正常示例中的代码之所以能成功,是因为我们在 ​​while​​ 无线循环中调用了另一个方法,而那个方法是被间歇性使用的,因此可以替换成功。

    总结

    本文我们讲了 Arthas 的概念以及具体的使用流程,Arthas 其实就是一个普通的 Java 程序,我们可以使用 ​​java -jar arthas-boot.jar​​ 来启动它,然后再选择我们要操作的 Java 进程,这样就可以实现状态监控和其他操作。

    文章的后半部分,我们介绍了 Arthas 的热更新功能,而热更新本质上只需要使用一个 ​​redefine​​ 命令来加载新的字节码文件就可以实现热更新了,但需要注意热更新不能替换正在运行的方法,它只能修改方法内部的业务代码,如果修改了类字段或者是更改了类方法,那么热更新就会执行失败。


    PS:热更新一时爽,但在实际使用时,要充分的评估生产环境的安全性。如果真要用,一定要让相关的负责人亲自处理,毕竟“稳定”和“安全”才是生产环境奉行的第一条铁律。



    关注公众号「Java中文社群」回复“干货”,获取 50 篇原创干货 Top 榜。


    漫画:Java如何实现热更新?_Java_15

    上一篇:驳《阿里「Java开发手册」中的1个bug》?
    下一篇:没有了
    网友评论