AsmToos的安装及操作
在OpenJDK里有一个AsmTools
项目,用来生成正确的或者不正确的java .class
文件,主要用来测试和验证。
我们知道直接修改.class
文件是很麻烦的,虽然有一些图形界面的工具,但还是很麻烦。
安装AsmToos
我这里有这个直接编译好的jar包,可以字节下载: https://download.csdn.net/download/shangrila_kun/11057760
-
环境
jdk8和ant
-
代码源
hg clone http:``//hg.openjdk.java.net/code-tools/asmtools
hg类似于git ,需要自行安装。centos系统下使用
yum intall hg
-
编译
cd asmtools/build
ant
编译之后会生成一个asmtools.jar的文件。注意查看编译后jar的路径.以下是我的编译后的生成位置。
releaseproduct:
[zip] Building zip: /tmp/asmtools-7.0-build-03-25-2019_12-38-PM/release/asmtools-7.0.zip
[move] Moving 1 file to /usr/local/asmtools-7.0-build/dist
测试
将jar包mv到与测试代码在同一目录中。
- 测试样例
public class Foo {
public static void main(String[] args) {
boolean flag = true;
if (flag) System.out.println("Hello, Java!");
if (flag == true) System.out.println("Hello, JVM!");
}
}
-
java Foo编译
javac Foo.java
-
生成jasm格式的字节码
java -jar asmtools.jar jdis Foo.class
super public class Foo
version 52: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
- 使用asmtools进行修改字节码(class->jasm)
java -jar asmtools.jar jdis Foo.class > Foo.jasm.1
之后Foo.jasm.1代码的内容如下:
super public class Foo
version 52: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
-
对jasm文件进行修改
awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_2")} 1' Foo.jasm.1 > Foo.jasm
super public class Foo
version 52: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_2;
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
-
jasm->class
java -jar asmtools.jar jasm Foo.jasm
此时class文件已经被修改了,修改后执行
-
运行class文件
[root@izwz93bcx7adgtozg4rvanz javacode]# java Foo
Hello, Java!
- 修改后的class代码为:
import java.io.PrintStream;
public class Foo
{
public static void main(String[] paramArrayOfString)
{
int i = 2;
if (i != 0) {
System.out.println("Hello, Java!");
}
if (i == 1) {
System.out.println("Hello, JVM!");
}
}
}