Skip to content

Instantly share code, notes, and snippets.

@rvprasad
Last active January 3, 2017 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rvprasad/e31260018b5513a4ed920b4e6519fa20 to your computer and use it in GitHub Desktop.
Save rvprasad/e31260018b5513a4ed920b4e6519fa20 to your computer and use it in GitHub Desktop.
Code to reproduce bug 9046671 in JDK 8.
/*
* Run this with ASM 5.1 (http://forge.ow2.org/project/showfiles.php?group_id=23) to generate X.class.
* Loading the generated X.class will cause the following error with JDK 9-ea, JDK 1.8.0_112, and Zulu 1.8.0_112.
*
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Stack map does not match the one at exception handler 13
Exception Details:
Location:
X.<init>(LX;)V @13: athrow
Reason:
Current frame's flags are not assignable to stack map frame's.
Current Frame:
bci: @0
flags: { flagThisUninit }
locals: { uninitializedThis, 'X' }
stack: { 'java/lang/Throwable' }
Stackmap Frame:
bci: @13
flags: { }
locals: { top, 'X' }
stack: { 'java/lang/Throwable' }
Bytecode:
0000000: 2abb 0004 5906 b700 09b7 000c b1bf
Exception Handler Table:
bci [0, 13] => handler: 13
Stackmap Table:
full_frame(@13,{Top,Object[#2]},{Object[#14]})
at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:2996)
at java.base/java.lang.Class.privateGetMethodRecursive(Class.java:3340)
at java.base/java.lang.Class.getMethod0(Class.java:3310)
at java.base/java.lang.Class.getMethod(Class.java:1987)
at java.base/sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:672)
at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:543)
*
*/
import java.io.*;
import java.nio.file.Files;
import java.util.*;
import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;
public class XDump {
public static void main(String[] s) throws Exception {
byte[] b = dump();
Files.write(new File("./X.class").toPath(), b);
}
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "X", null, "Y", null);
{
mv = cw.visitMethod(0, "<init>", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
Label begin = new Label();
mv.visitLabel(begin);
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
Label end = new Label();
mv.visitLabel(end);
mv.visitTryCatchBlock(begin, end, end, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "(LX;)V", null, null);
mv.visitCode();
Label begin = new Label();
mv.visitLabel(begin);
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
Label end = new Label();
mv.visitLabel(end);
mv.visitTryCatchBlock(begin, end, end, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}
/*
* The above issue can be addressed by splitting the try-catch handler as done here.
*/
import java.io.*;
import java.nio.file.Files;
import java.util.*;
import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;
public class XDump2 {
public static void main(String[] s) throws Exception {
byte[] b = dump();
Files.write(new File("./X.class").toPath(), b);
}
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "X", null, "Y", null);
{
mv = cw.visitMethod(0, "<init>", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
Label begin = new Label();
mv.visitLabel(begin);
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
Label end = new Label();
mv.visitLabel(end);
mv.visitTryCatchBlock(begin, end, end, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "(LX;)V", null, null);
mv.visitCode();
Label begin1 = new Label();
mv.visitLabel(begin1);
mv.visitVarInsn(ALOAD, 0);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
Label end1 = new Label();
mv.visitLabel(end1);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(Ljava/lang/Object;)V", false);
Label begin2 = new Label();
mv.visitLabel(begin2);
mv.visitInsn(RETURN);
Label end2 = new Label();
mv.visitLabel(end2);
Label handler1 = new Label();
mv.visitLabel(handler1);
mv.visitTryCatchBlock(begin1, end1, handler1, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
Label handler2 = new Label();
mv.visitLabel(handler2);
mv.visitTryCatchBlock(begin2, end2, handler2, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}
/*
* The above issue goes away if X's constructor does not have a parameter that is a sub-type of X.
*/
import java.io.*;
import java.nio.file.Files;
import java.util.*;
import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;
public class XDump3 {
public static void main(String[] s) throws Exception {
byte[] b = dump();
Files.write(new File("./X.class").toPath(), b);
}
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "X", null, "java/lang/Object", null);
{
mv = cw.visitMethod(0, "<init>", "(Ljava/lang/String;)V", null, null);
mv.visitCode();
Label begin = new Label();
mv.visitLabel(begin);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
Label end = new Label();
mv.visitLabel(end);
mv.visitTryCatchBlock(begin, end, end, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "(LY;)V", null, null);
mv.visitCode();
Label begin = new Label();
mv.visitLabel(begin);
mv.visitTypeInsn(NEW, "Y");
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESPECIAL, "Y", "<init>", "(I)V", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
Label end = new Label();
mv.visitLabel(end);
mv.visitTryCatchBlock(begin, end, end, "java/lang/Throwable");
mv.visitInsn(Opcodes.ATHROW);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}
/*
* Run this with ASM 5.1 (http://forge.ow2.org/project/showfiles.php?group_id=23) to generate X.class.
*/
import java.util.*;
import org.objectweb.asm.*;
public class YDump implements Opcodes {
public static void main(String[] s) throws Exception {
byte[] b = dump();
Files.write(new File("./Y.class").toPath(), b);
}
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(52, ACC_SUPER, "Y", null, "java/lang/Object", null);
{
mv = cw.visitMethod(0, "<init>", "(Ljava/lang/Object;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(0, "<init>", "(I)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment