import{_ as t,o,c as r,a as s,b as e,e as n,d as i,r as l}from"./app.391b0e4e.js";const c={},p=s("h1",{id:"retransform",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#retransform","aria-hidden":"true"},"#"),n(" retransform")],-1),d={href:"https://arthas.aliyun.com/doc/arthas-tutorials?language=en&id=command-mc-retransform",target:"_blank",rel:"noopener noreferrer"},u=s("code",null,"mc-retransform",-1),m=n(" online tutorial"),h=s("div",{class:"custom-container tip"},[s("p",{class:"custom-container-title"},"TIP"),s("p",null,[n("Load the external "),s("code",null,"*.class"),n(" files to retransform the loaded classes in JVM.")])],-1),v=n("Reference: "),f={href:"https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#retransformClasses-java.lang.Class...-",target:"_blank",rel:"noopener noreferrer"},k=n("Instrumentation#retransformClasses"),b=i(`
retransform /tmp/Test.class
retransform -l
retransform -d 1 # delete retransform entry
retransform --deleteAll # delete all retransform entries
retransform --classPattern demo.* # triger retransform classes
retransform -c 327a647b /tmp/Test.class /tmp/Test\\$Inner.class
retransform --classLoaderClass 'sun.misc.Launcher$AppClassLoader' /tmp/Test.class
$ retransform /tmp/MathGame.class
retransform success, size: 1, classes:
demo.MathGame
Load the specified .class file, then parse out the class name, and then retransform the corresponding class loaded in the jvm. Every time a .class
file is loaded, a retransform entry is recorded.
TIP
If retransform is executed multiple times to load the same class file, there will be multiple retransform entries.
$ retransform -l
Id ClassName TransformCount LoaderHash LoaderClassName
1 demo.MathGame 1 null null
Need to specify id:
retransform -d 1
retransform --deleteAll
$ retransform --classPattern demo.MathGame
retransform success, size: 1, classes:
demo.MathGame
WARNING
Note: For the same class, when there are multiple retransform entries, if retransform is explicitly triggered, the entry added last will take effect (the one with the largest id).
If you want to eliminate the impact after performing retransform on a class, you need to:
TIP
If you do not clear all retransform entries and trigger retransform again, the retransformed classes will still take effect when arthas stop.
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
mc /tmp/UserController.java -d /tmp
retransform /tmp/com/example/demo/arthas/user/UserController.class
jad
command to decompile bytecode, and then you can use other editors, such as vim to modify the source code.mc
command to compile the modified coderetransform
commandThe mc
command may fail. You can modify the code locally, compile it, and upload it to the server. Some servers do not allow direct uploading files, you can use the base64
command to bypass.
Convert the .class
file to base64 first, then save it as result.txt
Base64 < Test.class > result.txt
Login the server, create and edit result.txt
, copy the local content, paste and save
Restore result.txt
on the server to .class
Base64 -d < result.txt > Test.class
Use the md5 command to verify that the .class
files are consistent.
System.out.println
added below, only the run()
function will take effect.public class MathGame {
public static void main(String[] args) throws InterruptedException {
MathGame game = new MathGame();
while (true) {
game.run();
TimeUnit.SECONDS.sleep(1);
// This doesn't work because the code keeps running in while
System.out.println("in loop");
}
}
public void run() throws InterruptedException {
// This works because the run() function ends completely every time
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());
}
}
}