Skip to content

Instantly share code, notes, and snippets.

@lrytz
Created May 15, 2014 12:50
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 lrytz/32ead88e0024553d5584 to your computer and use it in GitHub Desktop.
Save lrytz/32ead88e0024553d5584 to your computer and use it in GitHub Desktop.
ASM InnerClass bug
package test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.*;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.util.TraceClassVisitor;
public class PositionsClassDump implements Opcodes {
public static void main(String[] args) {
try {
System.out.println("Visit inner classes before methods: everything is OK\n");
traceClass(dump(true));
System.out.println("\n\n\n\nVisit inner classes after methods: some InnerClass attributes are missing\n");
traceClass(dump(false));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void traceClass(byte[] bytes) {
ClassNode node = new ClassNode();
new ClassReader(bytes).accept(node, 0);
PrintWriter w = new PrintWriter(System.out);
node.accept(new TraceClassVisitor(w));
w.flush();
}
public static class Writer extends ClassWriter {
public Writer(int flags) {
super(flags);
}
@Override
protected String getCommonSuperClass(String type1, String type2) {
return "";
}
}
public static void visitInnerClasses(ClassWriter cw) {
cw.visitInnerClass("scala/reflect/internal/Positions$PosAssigner", "scala/reflect/internal/Positions", "PosAssigner", ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE);
cw.visitInnerClass("scala/reflect/internal/settings/MutableSettings$SettingValue", "scala/reflect/internal/settings/MutableSettings", "SettingValue", ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE);
cw.visitInnerClass("scala/reflect/internal/Positions$DefaultPosAssigner", "scala/reflect/internal/Positions", "DefaultPosAssigner", ACC_PUBLIC);
cw.visitInnerClass("scala/tools/nsc/settings/MutableSettings$BooleanSetting", "scala/tools/nsc/settings/MutableSettings", "BooleanSetting", ACC_PUBLIC);
cw.visitInnerClass("scala/tools/nsc/ast/Positions$ValidatingPosAssigner", "scala/tools/nsc/ast/Positions", "ValidatingPosAssigner", ACC_PUBLIC);
}
public static byte[] dump(boolean innerClassesFirst) throws Exception {
ClassWriter cw = new Writer(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER + ACC_ABSTRACT, "scala/tools/nsc/ast/Positions$class", null, "java/lang/Object", null);
if (innerClassesFirst)
visitInnerClasses(cw);
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "posAssigner", "(Lscala/tools/nsc/Global;)Lscala/reflect/internal/Positions$PosAssigner;", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "scala/reflect/internal/settings/MutableSettings$", "MODULE$", "Lscala/reflect/internal/settings/MutableSettings$;");
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Global", "settings", "()Lscala/tools/nsc/Settings;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Settings", "Yrangepos", "()Lscala/tools/nsc/settings/MutableSettings$BooleanSetting;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/reflect/internal/settings/MutableSettings$", "reflectSettingToBoolean", "(Lscala/reflect/internal/settings/MutableSettings$SettingValue;)Z", false);
Label l0 = new Label();
mv.visitJumpInsn(IFEQ, l0);
mv.visitFieldInsn(GETSTATIC, "scala/reflect/internal/settings/MutableSettings$", "MODULE$", "Lscala/reflect/internal/settings/MutableSettings$;");
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Global", "settings", "()Lscala/tools/nsc/Settings;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Settings", "debug", "()Lscala/tools/nsc/settings/MutableSettings$BooleanSetting;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/reflect/internal/settings/MutableSettings$", "reflectSettingToBoolean", "(Lscala/reflect/internal/settings/MutableSettings$SettingValue;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFNE, l1);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitFieldInsn(GETSTATIC, "scala/reflect/internal/settings/MutableSettings$", "MODULE$", "Lscala/reflect/internal/settings/MutableSettings$;");
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Global", "settings", "()Lscala/tools/nsc/Settings;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/tools/nsc/Settings", "Yposdebug", "()Lscala/tools/nsc/settings/MutableSettings$BooleanSetting;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "scala/reflect/internal/settings/MutableSettings$", "reflectSettingToBoolean", "(Lscala/reflect/internal/settings/MutableSettings$SettingValue;)Z", false);
Label l2 = new Label();
mv.visitJumpInsn(IFEQ, l2);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitTypeInsn(NEW, "scala/tools/nsc/ast/Positions$ValidatingPosAssigner");
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "scala/tools/nsc/ast/Positions$ValidatingPosAssigner", "<init>", "(Lscala/tools/nsc/Global;)V", false);
Label l3 = new Label();
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitTypeInsn(NEW, "scala/reflect/internal/Positions$DefaultPosAssigner");
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "scala/reflect/internal/Positions$DefaultPosAssigner", "<init>", "(Lscala/reflect/internal/SymbolTable;)V", false);
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"scala/reflect/api/Trees$Traverser"});
mv.visitInsn(ARETURN);
mv.visitMaxs(3, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "$init$", "(Lscala/tools/nsc/Global;)V", null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
}
if (!innerClassesFirst)
visitInnerClasses(cw);
cw.visitEnd();
return cw.toByteArray();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment