Modifying <clinit> with ASM
Hello, I have a little problem with ASM. It creates a class with a bytecode error:
Exception in thread "main" java.lang.VerifyError: Bad instruction
Exception Details:
Location:
me/test/Main.<clinit>()V @0: wide
Reason:
Error exists in the bytecode
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
When I use the following code to enter code into a method <clinit>that fills a static byte array with the variable "key" ( byte[]):
if (key.length > 128)
this.visitVarInsn(SIPUSH, key.length);
else
this.visitVarInsn(BIPUSH, key.length);
this.visitVarInsn(NEWARRAY, 8);
for (int i = 0; i < key.length; i++) {
this.visitInsn(DUP);
if (i > 127) {
this.visitVarInsn(SIPUSH, i + 32768);
} else if (i < 6) {
switch (i) {
case 0:
this.visitInsn(ICONST_0);
break;
case 1:
this.visitInsn(ICONST_1);
break;
case 2:
this.visitInsn(ICONST_2);
break;
case 3:
this.visitInsn(ICONST_3);
break;
case 4:
this.visitInsn(ICONST_4);
break;
case 5:
this.visitInsn(ICONST_5);
break;
default:
System.out.println("Logic mistake!");
break;
}
}
else {
this.visitVarInsn(BIPUSH, i);
}
if (key[i] < 6 && key[i] >= 0) {
switch (key[i]) {
case 0:
this.visitInsn(ICONST_0);
break;
case 1:
this.visitInsn(ICONST_1);
break;
case 2:
this.visitInsn(ICONST_2);
break;
case 3:
this.visitInsn(ICONST_3);
break;
case 4:
this.visitInsn(ICONST_4);
break;
case 5:
this.visitInsn(ICONST_5);
break;
default:
System.out.println("Logic mistake!");
break;
}
} else {
this.visitVarInsn(BIPUSH, key[i]);
}
this.visitInsn(BASTORE);
0
1 answer
The main reason for incorrect code is your multiple misuse visitVarInsn.
visitVarInsn , . , , , . ,
this.visitVarInsn(NEWARRAY, 8);
this.visitIntInsn(NEWARRAY, Opcodes.T_BYTE);
this.visitVarInsn(SIPUSH, key.length); this.visitVarInsn(BIPUSH, key.length);, , . ,
if (key.length > 128)
this.visitVarInsn(SIPUSH, key.length);
else
this.visitVarInsn(BIPUSH, key.length);
, 128. , this.visitVarInsn(SIPUSH, i + 32768); + 32768 .
, . , , , . , InstructionAdapter, MethodVisitor, iconst(int), ICONST_x, BIPUSH, SIPUSH LDC. , GeneratorAdapter , push(int) .
, GeneratorAdapter, ,
push(key.length);
newArray(Type.BYTE_TYPE);
for(int i = 0; i < key.length; i++) {
this.visitInsn(Opcodes.DUP);
push(i);
push(key[i]);
visitInsn(Opcodes.BASTORE);
}
+3