说明:
在学习极客时间——《深入拆解JVM虚拟机》专栏中,有用到asmtools这样一个工具,用以修改class文件。
一.获取工具
获取工具方法:
-
自己构建asmtools.jar:https://www.cnblogs.com/yelongsan/p/9674723.html
-
直接下载asmtools.jar:https://yun.515code.com/file/asmtools.jar
另外,下载 JD-GUI ,它是".class"文件的反编译工具。
拿到jar包后,我们进入命令行即可。
二.测试
1.生成一个java文件,名字为 Foo.java
1 2 3 4 5 6 7 8
| echo ' public class Foo { public static void main(String[] args) { boolean boolValue = true; if (boolValue) System.out.println("Hello, Java!"); if (boolValue == true) System.out.println("Hello, JVM!"); } }' > Foo.java
|
2.编译并执行
1 2 3 4 5 6
| javac Foo.java java Foo
Hello, Java! Hello, JVM!
|
3.将class文件转换为jasm文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| java -jar asmtools.jar jdis Foo.class > Foo.jasm
super public class Foo version 55:0 {
public Method "<init>":"()V" stack 1 locals 1 { aload_0; invokespecial Method java/lang/Object."<init>":"()V"; return; }
public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 { iconst_1; istore_1; iload_1; ifeq L14; getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, Java!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L14: stack_frame_type append; locals_map int; iload_1; iconst_1; if_icmpne L27; getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ldc String "Hello, JVM!"; invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; L27: stack_frame_type same; return; }
} // end Class Foo
|
我们都知道,boolean类型为true时在虚拟机用1代替(boolValue在虚拟机中值为1)
接下来,将第一个 iconst_1 改为 iconst_2( 相当于把boolValue值改为2 )
4.将jasm文件转换为class文件
1
| java -jar asmtools.jar jasm Foo.jasm
|
5.使用 JD-GUI 打开 Foo.class(内容如下)
1 2 3 4 5 6 7 8 9
| public class Foo { public static void main(String[] paramArrayOfString) { byte b = 2; if (b != 0) System.out.println("Hello, Java!"); if (b == 1) System.out.println("Hello, JVM!"); } }
|
可以看到,我们成功通过修改class文件把boolValue的值改为2了
再次执行:
可以看到,第二个if条件不成立
三.总结
- 学会使用asmtools工具修改class文件:
- 由 class 文件生成 jasm 文件:
java -jar asmtools.jar jdis Foo.class > Foo.jasm
- 由 jasm 文件生成 class 文件:
java -jar asmtools.jar jasm Foo.jasm
- 使用JD-GUI可以反编译class文件
- 通过上面简单的小例子,证实了boolean类型在虚拟机中值为0或1,有趣的是 if (boolValue) 会被翻译成 if (b != 0)