redefine¶
Load the external
*.classfiles to re-define the loaded classes in JVM.
Reference: Instrumentation#redefineClasses
Notes: Re-defined classes cannot be restored. There are chances that redefining may fail due to some reasons, for example: there’s new field introduced in the new version of the class, pls. refer to JDK’s documentation for the limitations.
The
resetcommand is not valid for classes that have been processed byredefine. If you want to reset, you needredefinethe original bytecode.
The
redefinecommand will conflict with thejad/watch/trace/monitor/ttcommands. After executingredefine, if you execute the above mentioned command, the bytecode of the class will be reset. The reason is that in the JDKredefineandretransformare different mechanisms. When two mechanisms are both used to update the bytecode, only the last modified will take effect.
Options¶
| Name | Specification |
|---|---|
[c:] |
hashcode of the class loader |
[p:] |
absolute path of the external *.class, multiple paths are separated with 'space' |
Usage¶
redefine /tmp/Test.class
redefine -c 327a647b /tmp/Test.class /tmp/Test$Inner.classUse with the jad/mc command¶
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
mc /tmp/UserController.java -d /tmp
redefine /tmp/com/example/demo/arthas/user/UserController.classUse
jadcommand to decompile bytecode, and then you can use other editors, such as vim to modify the source code.mccommand to compile the modified codeLoad new bytecode with
redefinecommand
Tips for uploading .class files to the server¶
The 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
.classfile to base64 first, then save it as result.txtBase64 < Test.class > result.txt
Login the server, create and edit
result.txt, copy the local content, paste and saveRestore
result.txton the server to.classBase64 -d < result.txt > Test.class
Use the md5 command to verify that the
.classfiles are consistent.
Restrictions of the redefine command¶
New field/method is not allowed
The function that is running, no exit can not take effect, such as the new
System.out.printlnadded below, only therun()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()); } }