Arthas热加载运行中的Java代码

背景

在排查线上问题时,经常发现是低级错误引起,类似于NPE、变量名写错了等等。对于这种问题,我们往往只需要改动一两行代码就能验证并修复问题。实际过程中,我们需要重新打包工程,然后走一遍发布流程。在处理线上问题的时候,等待发布页会变得很漫长,运气不好,可能发布完后发现问题并没有解决,就会非常崩溃。这就需要一种方便的方式,可以直接修改运行中的代码,让我们能快速验证问题是否解决。

概念简介

热部署是指在不停止进程的情况下,重新加载新的java代码。例如,修改完方法里的代码后,将修改的逻辑重新注入到Jvm里。Arthas就给我们提供了这样的功能。

热部署过程

修改java代码

如果没有原始java文件,通过Arthas的jad命令可以反编译获得java文件:

> jad --source-only com.controller.TestController > /tmp/TestController .java

--source-only参数控制输出内容里只包含源代码。不然会一起输出ClassLoader和Location文件位置。

重新编译java代码

使用Arthas时,编译java代码需用到原class文件的类加载器。

使用`sc`命令查到原class文件的类加载器

> sc -d com.controller.TestController

class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@49c2faae
+-sun.misc.Launcher$AppClassLoader@42a57993
+-sun.misc.Launcher$ExtClassLoader@2d83b924
classLoaderHash 49c2faae

在输出内容的最后一行,显示了当前类的加载器。

使用`mc`命令编译java文件

> mc -c 49c2faae /tmp/AliAdminController.java -d /tmp

Memory compiler output:
/tmp/com/controller/TestController .class

编译命令会因为各种原因而编译失败,这时候可以尝试在本地把原始java传上去,不使用反编译的数据。

下面是编译失败的提示:

Memory compiler error, exception message: Compilation Error

重新加载新的class文件

> redefine /tmp/com/dingtone/videomaster/feed/web/controller/feign/AliAdminController.class
redefine success, size: 1, classes:
com.dingtone.videomaster.feed.web.controller.feign.AliAdminController

小结

redefine命令返回redefine success就代表热部署成功。在使用热加载可以修改方法体里的代码,但是也会有一些限制,不能修改class的schema,包括新增字段/方法。

你可能感兴趣的:(java,开发语言,Arthas)