背景

现场出现静态变量定义错误的情况,因为生产问题又不能重新发包。所以需要热部署更新类。

此处为转载


以某个界面为例

arthas文档 kubernates arthas部署_java

找到程序Action层或者Controller层
类的全路径:
com.ailk.openbilling.ams.action.freeResourceQuery.FreeResourceQueryActionImp
要观察的方法名:
queryFreeRes

1、热更新类

更新前:

arthas文档 kubernates arthas部署_arthas文档 kubernates_02

(1)、将要反编译的文件 反编译到指定目录

命令:

jad com.ailk.openbilling.ams.action.freeResourceQuery.FreeResourceQueryActionImpl > /home/acctuser/cz/FreeResourceQueryActionImpl.java

结果:

arthas文档 kubernates arthas部署_反编译_03

arthas文档 kubernates arthas部署_反编译_04

(2)、修改文件内容

arthas文档 kubernates arthas部署_java_05

(3)、查找要更新的类的classLoader的哈希码

命令:

sc -d *FreeResourceQueryActionImpl | grep classLoaderHash

结果:

arthas文档 kubernates arthas部署_热更新_06

(4)、编译修改后的文件

命令:
mc -c 2b53eef4 /home/acctuser/cz/FreeResourceQueryActionImpl.java -d /home/acctuser/cz

结果:(编译报错)

arthas文档 kubernates arthas部署_热更新_07

问题解决
  • 查看日志:
  • arthas文档 kubernates arthas部署_热更新_08

  • 查看编译后的源码(发现头部多了好多类加载信息之类的东西)
  • arthas文档 kubernates arthas部署_arthas文档 kubernates_09

  • 重新反编译源码并且加上 --source-only 表示只输出源码
    命令:
    jad --source-only com.ailk.openbilling.ams.action.freeResourceQuery.FreeResourceQueryActionImpl > /XXX/XXX/cz/FreeResourceQueryActionImpl.java
  • 结果:(反编译成功)
  • arthas文档 kubernates arthas部署_反编译_10

  • 重新修改.java文件后再次编译
  • 又编译报错了
  • arthas文档 kubernates arthas部署_arthas文档 kubernates_11

  • 直接把本地修改好的.java文件放上去使用arthas编译成功生成了.class文件
  • arthas文档 kubernates arthas部署_反编译_12

  • 继续热更新代码:
    命令:
    redefine /home/acctuser/cz/com/ailk/openbilling/ams/action/freeResourceQuery/FreeResourceQueryActionImpl.class
  • 结果失败:(提示增加或者删除了类或方法)
  • arthas文档 kubernates arthas部署_java_13

  • 查看编译后的代码发现多了一个static{}和Log;
  • 重新将反编译后的.java文件放到本地eclipse中将里面未指定泛型的报错(反编译会擦除泛型)地方修改掉,放到服务器重新使用mc -c 命令编译然后再热更新
    热更新成功:
  • arthas文档 kubernates arthas部署_arthas文档 kubernates_14

更新后:

arthas文档 kubernates arthas部署_java_15

一波三折终于热更新成功…