当我尝试这个
public class MainDump implements Opcodes {
public static byte[] dump() throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "Main", null, "java/lang/Object", null);
cw.visitSource("Main.java", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(1, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(RETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "LMain;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
mv.visitCode();
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 1);
mv.visitVarInsn(ILOAD, 1);
Label l2 = new Label();
mv.visitJumpInsn(IFEQ, l2);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 2);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_APPEND, 1, new Object[]{Opcodes.INTEGER}, 0, null);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 3);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
public static void main(String... ignored) throws Exception {
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
byte[] dump = dump();
defineClass.invoke(Thread.currentThread().getContextClassLoader(), dump, 0, dump.length);
new Main().test();
}
}
这有效,但是如果我放弃堆栈帧调整,我会收到此错误
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 8
Exception Details:
Location:
Main.test()V @3: ifeq
Reason:
Expected stackmap frame at this location.
Bytecode:
0000000: 033c 1b99 0005 033d b1
简而言之,对于Java 7,堆栈操作不足以通过有效性。