retransform

加载外部的.class文件,retransform jvm已加载的类

命令选项 描述
-c, --classloader <hash> 指定ClassLoader的哈希值
--classLoaderClass <class-name> 指定ClassLoader的类名
--classPattern <pattern> 通过模式匹配类触发retransform
-d, --delete <id> 删除给定id的retransform entry
--deleteAll 删除所有retransform entry
--limit <number> 限制dump class的数量,默认50
-l, --list 列出所有retransform entry
-h, --help 帮助
<classFilePaths> class文件路径

示例

修改MathGame代码如下

public void run() throws InterruptedException {
        System.out.println("I'm running again!");
        try {
            int number = random.nextInt()/10000;
            List<Integer> primeFactors = primeFactors(number);
            print(number, primeFactors);

        } catch (Exception e) {
            System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());
        }
    }
# 编译修改后的java文件
[arthas@13728]$ mc -d /tmp /tmp/MathGame.java
Memory compiler output:
C:\tmp\demo\MathGame.class
Affect(row-cnt:1) cost in 50 ms.

# retransform MathGame
[arthas@13728]$ retransform /tmp/demo/MathGame.class
redefine success, size: 1, classes:
demo.MathGame
# retransform后控制台输出如下
I'm running again!
illegalArgumentCount:4779, number is: -16285, need >= 2
I'm running again!
illegalArgumentCount:4780, number is: -164989, need >= 2
I'm running again!
illegalArgumentCount:4781, number is: -36742, need >= 2

# 列出当前retransform entry列表
[arthas@13728]$ retransform -l
Id              ClassName       TransformCount  LoaderHash      LoaderClassName
59              demo.MathGame   1               null            null

# 还原retransform类
retransform --deleteAll
reset

注意

  • 不允许新增加 field/method
  • 正在运行的函数,没有结束不能生效
  • 如果多次执行 retransform 加载同一个 class 文件,则会有多条 retransform entry
  • 对于同一个类,当存在多个 retransform entry 时,如果显式触发 retransform ,则最后添加的 entry 生效(id 最大的)
  • 如果不清除掉所有的 retransform entry,并重新触发 retransform ,则 arthas stop 时,retransform 过的类仍然生效。
  • 删除所有retransform entry,可用reset命令还原