1. 关于asmtools.jar
用途:转换过程 “.class文件 -> 字节码指令(类似汇编语言)文件 -> .class文件”,只需要修改“字节码指令(类似汇编语言)文件”就能改变一个“.class文件”的运行结果。
2. 获取方式asmtools.jar
下载url:https://ci.adoptopenjdk.net/view/Dependencies/job/asmtools/lastSuccessfulBuild/artifact/
3. 示例
Foo.java
package org.example;
public class Foo {
static boolean boolValue;
public static void main(String[] args) {
boolValue = true; // 将这个true替换为2或者3,再看看打印结果
if (boolValue) System.out.println("Hello, Java!");
if (boolValue == true) System.out.println("Hello, JVM!");
}
}
1)编译成.class文件后,运行命令反编译成字节码指令文件:
~/Demo/jvm_learning/ch2/target/classes/org/example$ java -cp ~/Downloads/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm
生成的字节码指令文件Foo.jasm内容如下:
// class version 51.0 (51)
// access flags 0x21
public class org/example/Foo {
// compiled from: Foo.java
// access flags 0x8
static Z boolValue
// access flags 0x1
public <init>()V
L0
LINENUMBER 3 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lorg/example/Foo; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 6 L0
ICONST_1
PUTSTATIC org/example/Foo.boolValue : Z
L1
LINENUMBER 7 L1
GETSTATIC org/example/Foo.boolValue : Z
IFEQ L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello, Java!"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 8 L2
FRAME SAME
GETSTATIC org/example/Foo.boolValue : Z
ICONST_1
IF_ICMPNE L3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello, JVM!"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L3
LINENUMBER 9 L3
FRAME SAME
RETURN
L4
LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
MAXSTACK = 2
MAXLOCALS = 1
}
2)运行gedit Foo,jasm,将26行代码ICONST_1改成ICONST_2后保存。
3)再运行命令编译成字节码文件Foo.class:
~/Demo/jvm_learning/ch2/target/classes/org/example$ java -cp ~/Downloads/asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm
此时运行Foo.class的结果没有输出:
~/Demo/jvm_learning/ch2/target/classes$ java org.example.Foo
~/Demo/jvm_learning/ch2/target/classes$
再重复上述步骤1)~3),其中将26行代码 ICONST_2改成ICONST_3,此时运行Foo.class的结果输出是:
~/Demo/jvm_learning/ch2/target/classes$ java org.example.Foo
Hello, Java!
Hello, JVM!
~/Demo/jvm_learning/ch2/target/classes$