记录一下修改class文件以及使用命令行执行class文件
- 参考《Java核心技术 卷2》
1. 编写代码
在包jdk.test.classLoader
下创建类VerifyTest
,对应磁盘目录是D://workspace/Test/jdk.test.classloader
package jdk.test.classLoader;
public class VerifyTest {
static int fun() {
int m, n;
m = 1;
n = 2;
return m + n;
}
public static void main(String[] args) {
System.out.println(fun());
}
}
2. 编译
javac VerifyTest.java
;
3.反编译看字节码
$ javap -c VerifyTest.class
Compiled from "VerifyTest.java"
public class jdk.test.classLoader.VerifyTest {
public jdk.test.classLoader.VerifyTest();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
static int fun();
Code:
0: iconst_1
1: istore_0
2: iconst_2
3: istore_1
4: iload_0
5: iload_1
6: iadd
7: ireturn
public static void main(java.lang.String[]);
Code:
0: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #27 // Method fun:()I
6: invokevirtual #29 // Method java/io/PrintStream.println:(I)V
9: return
}
把方法fun的助记符的字节码(16进制找到)
static int fun();
Code:
0: iconst_1 04
1: istore_0 3B
2: iconst_2 05
3: istore_1 3C
4: iload_0 1A
5: iload_1 1B
6: iadd 60
7: ireturn AC
修改字节码文件
把3C改成3B,这样第一个局部变量就被初始化两次,而第二个变量没有被初始化(这是虚拟机不接受的)
再反编译一下:
$ javap -c VerifyTest.class
Compiled from "VerifyTest.java"
public class jdk.test.classLoader.VerifyTest {
public jdk.test.classLoader.VerifyTest();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
static int fun();
Code:
0: iconst_1
1: istore_0
2: iconst_2
3: istore_0 //此处变了
4: iload_0
5: iload_1
6: iadd
7: ireturn
public static void main(java.lang.String[]);
Code:
0: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #27 // Method fun:()I
6: invokevirtual #29 // Method java/io/PrintStream.println:(I)V
9: return
}
执行
到包的根目录下执行
$ pwd
/d/workspace/Test/bin
$ java -classpath . jdk.test.classLoader.VerifyTest
java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
jdk/test/classLoader/VerifyTest.fun()I @5: iload_1
Reason:
Type top (current frame, locals[1]) is not assignable to integer
Current Frame:
bci: @5
flags: { }
locals: { integer }
stack: { integer }
Bytecode:
0x0000000: 043b 053b 1a1b 60ac
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main"
不验证:
$ java -noverify jdk.test.classLoader.VerifyTest
2
网友评论