All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kilim.tools.DumpClass Maven / Gradle / Ivy

Go to download

Coroutines, continuations, fibers, actors and message passing for the JVM

There is a newer version: 2.0.2-jdk7
Show newest version
/* Copyright (c) 2006, Sriram Srinivasan
 *
 * You may distribute this software under the terms of the license 
 * specified in the file "License"
 */

package kilim.tools;
import static kilim.analysis.Utils.dedent;
import static kilim.analysis.Utils.indent;
import static kilim.analysis.Utils.p;
import static kilim.analysis.Utils.pn;
import static kilim.analysis.Utils.resetIndentation;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import kilim.analysis.TypeDesc;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * Equivalent to javap -c -l -private, but the output is in jasmin's format 
 * meant to be parseable by Asm.
 * @author sriram
 */
public class DumpClass extends ClassVisitor implements Opcodes {
    
    static boolean lineNumbers = true;
    
    public static void main(String[] args) throws IOException {
        String name = args.length == 2 ? args[1] : args[0];
        
        if (name.endsWith(".jar")) {
            try {
                Enumeration e = new JarFile(name).entries();
                while (e.hasMoreElements()) {
                    ZipEntry en = (ZipEntry) e.nextElement();
                    String n = en.getName();
                    if (!n.endsWith(".class")) continue;
                    n = n.substring(0, n.length() - 6).replace('/','.');
                    new DumpClass(n);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            new DumpClass(name);
        }
    }
    

    public DumpClass(InputStream is) throws IOException {
        super(ASM7_EXPERIMENTAL);
        ClassReader cr = new ClassReader(is);
        cr.accept(this, /*flags*/ 0);
    }

    public DumpClass(String className) throws IOException {
        super(ASM7_EXPERIMENTAL);
        ClassReader cr;
        if (className.endsWith(".class")) {
            FileInputStream fis = new FileInputStream(className);
            cr = new ClassReader(fis);
        } else {
            cr = new ClassReader(className);
        }
        cr.accept(this, /*flags*/ClassReader.EXPAND_FRAMES);
    }

    public void visit(int version, int access, String name, String signature, 
            String superName, String[] interfaces) 
    {
        p(".class "); 
        p(Modifier.toString(access));
        p(" ");
        pn(name);
        if (superName != null) 
            pn(".super " + superName);
        
        if (interfaces != null) {
            for (int i = 0; i < interfaces.length; i++) {
                p(".implements ");
                pn(interfaces[i]);
            }
        }
    }

    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        pn(".annotation " + (visible ? "visible " : "") + desc);
        pn(".end annotation");
        return new DummyAnnotationVisitor();
    }

    public void visitAttribute(Attribute attr) {}

    public void visitEnd() {}

    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
        p(".field ");
        p(Modifier.toString(access));
        p(" ");
        p(name);
        p(" ");
        p(desc);
        if (value != null) {
            p(" = ");
            if (value instanceof String) {
                pn("\"" + value + "\"");
            } else {
                pn(value.toString());
            }
        } else {
            pn();
        }
        return null;
    }

    public void visitInnerClass(String name, String outerName, String innerName, int access) {
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        pn("");
        pn("; -------------------------------------------------------------");
        p(".method ");
        p(Modifier.toString(access));
        p(" ");
        p(name);
        pn(desc);
        pn("; signature = " + signature);
        pn("; -------------------------------------------------------------\n");
        if (exceptions != null) {
            for (int i = 0; i < exceptions.length; i++) {
                p(".throws ");
                pn(exceptions[i]);
            }
        }
        return new DumpMethodVisitor();
    }

    public void visitOuterClass(String owner, String name, String desc) {
    }

    public void visitSource(String source, String debug) {}
}

class DummyAnnotationVisitor extends AnnotationVisitor {
    public DummyAnnotationVisitor() {
        super(Opcodes.ASM7_EXPERIMENTAL);
        // TODO Auto-generated constructor stub
    }
    public void visit(String name, Object value) {
//        System.out.println("visit: name = " + name + ", value = "  + value);
    }
    public AnnotationVisitor visitAnnotation(String name, String desc) {
//        System.out.println("visitAnnotation: name = " + name + ", desc = " + desc);
        return this;
    }

    public AnnotationVisitor visitArray(String name) {
//        System.out.println("visitArray: name = " + name);
        return this;
    }

    public void visitEnd() {
//        System.out.println("visitEnd");
    }

    public void visitEnum(String name, String desc, String value) {
//        System.out.println("visitEnum: " + name + ", desc = "  + desc + ", value = " + value);
    }
}

class DumpMethodVisitor extends MethodVisitor implements Opcodes {

    public DumpMethodVisitor() {
        super(Opcodes.ASM7_EXPERIMENTAL);
    }

    static String[] os = {
        "nop","aconst_null","iconst_m1","iconst_0","iconst_1","iconst_2",
        "iconst_3","iconst_4","iconst_5","lconst_0","lconst_1","fconst_0",
        "fconst_1","fconst_2","dconst_0","dconst_1","bipush","sipush",
        "ldc","ldc_w","ldc_w","iload","lload","fload","dload","aload",
        "iload_0","iload_1","iload_2","iload_3","lload_0","lload_1","lload_2",
        "lload_3","fload_0","fload_1","fload_2","fload_3","dload_0","dload_1",
        "dload_2","dload_3","aload_0","aload_1","aload_2","aload_3","iaload",
        "laload","faload","daload","aaload","baload","caload","saload",
        "istore","lstore","fstore","dstore","astore","istore_0","istore_1",
        "istore_2","istore_3","lstore_0","lstore_1","lstore_2","lstore_3",
        "fstore_0","fstore_1","fstore_2","fstore_3","dstore_0","dstore_1",
        "dstore_2","dstore_3","astore_0","astore_1","astore_2","astore_3",
        "iastore","lastore","fastore","dastore","aastore","bastore",
        "castore","sastore","pop","pop2","dup","dup_x1","dup_x2","dup2",
        "dup2_x1","dup2_x2","swap","iadd","ladd","fadd","dadd","isub",
        "lsub","fsub","dsub","imul","lmul","fmul","dmul","idiv","ldiv",
        "fdiv","ddiv","irem","lrem","frem","drem","ineg","lneg","fneg","dneg",
        "ishl","lshl","ishr","lshr","iushr","lushr","iand","land","ior","lor",
        "ixor","lxor","iinc","i2l","i2f","i2d","l2i","l2f","l2d","f2i","f2l",
        "f2d","d2i","d2l","d2f","i2b","i2c","i2s","lcmp","fcmpl","fcmpg",
        "dcmpl","dcmpg","ifeq","ifne","iflt","ifge","ifgt","ifle","if_icmpeq",
        "if_icmpne","if_icmplt","if_icmpge","if_icmpgt","if_icmple","if_acmpeq",
        "if_acmpne","goto","jsr","ret","tableswitch","lookupswitch","ireturn",
        "lreturn","freturn","dreturn","areturn","return","getstatic",
        "putstatic","getfield","putfield","invokevirtual","invokespecial",
        "invokestatic","invokeinterface","unused","new","newarray","anewarray",
        "arraylength","athrow","checkcast","instanceof","monitorenter",
        "monitorexit","wide","multianewarray","ifnull","ifnonnull","goto_w","jsr_w"
    };
    int line = 0;
    static StringBuilder fsb = new StringBuilder(100);
    static Formatter formatter = new Formatter(fsb);
    public void ppn(String s) {
        if (DumpClass.lineNumbers) {
            fsb.setLength(0);
            formatter.format("%-70s ; %d", s, (line++));
            pn(fsb.toString());
        } else {
            pn(s); 
        }
    }

    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
        ppn(os[opcode] + " " + owner + "/" + name + " " + desc);
    }

    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
        pn("; Frame " + type);
        
        p (";  Locals - ");
        for(int i = 0; i < nLocal; i++) {
            Object o = local[i];
            System.out.print("#" + i + "."  + type(o) + "  ");
        }
        System.out.println();
        p(";  Stack - ");
        for(int i = 0; i < nStack; i++) {
            Object o = stack[i];
            System.out.print("#" + i + "."  + type(o) + "  ");
        }
        System.out.println("");
    }

    private String type(Object o) {
        if (o == null) {
            return "null";
        } else if (o instanceof Integer) {
            switch (((Integer)o).intValue()) {
            case 0: return "Top";
            case 1: return "Integer";
            case 2: return "Float";
            case 3: return "Double";
            case 4: return "Long";
            case 5: return "Null";
            case 6: return "Uninitialized_This";            }
        } else if (o instanceof String) {
            return (String)o;
        }
        return "??UNKNOWN??" + o.getClass() + ":" + o;
    }

    public void visitIincInsn(int var, int increment) {
        ppn("iinc " + var + " " + increment);
    }

    public void visitInsn(int opcode) {
        ppn(os[opcode]);
    }

    public void visitIntInsn(int opcode, int operand) {
        if (opcode == NEWARRAY) {
            String t = "UNDEFINED";
            switch (operand) {
                case T_BOOLEAN: t = " boolean"; break;
                case T_CHAR:    t = " char"; break;
                case T_FLOAT:   t = " float"; break;
                case T_DOUBLE:  t = " double"; break;
                case T_BYTE:    t = " byte"; break;
                case T_SHORT:   t = " short"; break;
                case T_INT:     t = " int"; break;
                case T_LONG:    t = " long"; break;
            }
            ppn(os[opcode] + t);
        } else {
            ppn(os[opcode] + " " +operand);
        }
    }

    public void visitJumpInsn(int opcode, Label label) {
        ppn(os[opcode] + " " + lab(label));
    }

    public void visitLabel(Label label) {
        dedent(2);
        pn(lab(label) + ":");
        indent(2);
    }

    public void visitLdcInsn(Object cst) {
        String op = (cst instanceof Double) || (cst instanceof Long) ? "ldc2_w " : "ldc ";
        String type = (cst instanceof String) ? "\"" + esc((String)cst) + "\"" : cst.toString();
        ppn(op  + type);
    }

    public void visitLineNumber(int line, Label start) {
        pn(".line " + line);
    }

    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
        pn(".var " + index + " is "+  name + " " + desc + " from " + lab(start) + " to " + lab(end));
    }

    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
        ppn("lookupswitch");
        indent(4);
        for (int i= 0; i < keys.length; i++) {
            pn(keys[i] + ": " + lab(labels[i]));
        }
        pn("default: " + lab(dflt));
        dedent(4);
    }

    public void visitMethodInsn(int opcode, String owner, String name, String desc,boolean itf) {
        String str = os[opcode] + " " + owner + "/" + name + desc;
        if (opcode == INVOKEINTERFACE) {
            ppn(str + ", " + (TypeDesc.getNumArgumentTypes(desc)+1));
        } else {
            ppn(str);
        }
    }
    
    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
            Object... bsmArgs) {
        ppn("invokedynamic " + name + desc);
        indent(4);
        pn("; bootstrap = " + bsm.getOwner() + "." + bsm.getName() + bsm.getDesc());
        for (int i = 0; i < bsmArgs.length; i++) {
            pn("; arg[" + i + "] = " + bsmArgs[0]);
        }
        dedent(4);
    }

    public void visitMultiANewArrayInsn(String desc, int dims) {
        ppn("multinewarray " + desc + " " + dims) ;
    }

    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
        ppn("tableswitch  " + min);
        indent(4);
        for (int i = min; i <= max; i++) {
            pn(lab(labels[i - min]));
        }
        pn("default: " + lab(dflt));
        dedent(4);
    }

    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
        pn(".catch " + type + " from " + lab(start) + " to " + lab(end) + 
                " using " + lab(handler));
    }

    public void visitTypeInsn(int opcode, String desc) {
        ppn(os[opcode] + " " +desc);
    }

    public void visitVarInsn(int opcode, int var) {
        ppn(os[opcode] + " " + var);
    }
    
    HashMap labels = new HashMap();
    int labCount = 1;
    private String lab(Label label) {
        String ret = labels.get(label);
        if (ret == null) {
            ret = "L"+ labCount++;
            labels.put(label, ret);
        }
        return ret;
    }
    public AnnotationVisitor visitAnnotationDefault() {
        return new DummyAnnotationVisitor();
    }
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        pn(".annotation " + (visible ? "visible " : "") + desc);
        pn(".end annotation");
        return new DummyAnnotationVisitor();
    }
    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
        return new DummyAnnotationVisitor();
    }
    public void visitAttribute(Attribute attr) {
    }
    public void visitCode() {
        indent(4);
    }
    public void visitMaxs(int maxStack, int maxLocals) {
        pn(".limit stack " + maxStack);
        pn(".limit locals " + maxLocals);
    }
    public void visitEnd() {
        resetIndentation();
        pn(".end method");
    }
    
    private static String esc(String s) {
        return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy