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

com.zving.framework.thirdparty.asm.ClassReader Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
// Decompiled by DJ v3.12.12.101 Copyright 2016 Atanas Neshkov  Date: 2016/5/14 12:59:50
// Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   ClassReader.java

package com.zving.framework.thirdparty.asm;

import java.io.IOException;
import java.io.InputStream;

import com.zving.preloader.Util;

// Referenced classes of package com.zving.framework.thirdparty.asm:
//            Item, ClassWriter, ByteVector, Attribute, 
//            Context, ClassVisitor, FieldVisitor, MethodWriter, 
//            MethodVisitor, AnnotationVisitor, Label, Handle, 
//            Type, Opcodes

public class ClassReader
{

    public ClassReader(byte b[])
    {
        this(b, 0, b.length);
    }

    public ClassReader(byte b[], int off, int len)
    {
        this.b = b;
        if(readShort(off + 6) > 51)
            throw new IllegalArgumentException();
        items = new int[readUnsignedShort(off + 8)];
        int n = items.length;
        strings = new String[n];
        int max = 0;
        int index = off + 10;
        for(int i = 1; i < n; i++)
        {
            items[i] = index + 1;
            int size;
            switch(b[index])
            {
            case 3: // '\003'
            case 4: // '\004'
            case 9: // '\t'
            case 10: // '\n'
            case 11: // '\013'
            case 12: // '\f'
            case 18: // '\022'
                size = 5;
                break;

            case 5: // '\005'
            case 6: // '\006'
                size = 9;
                i++;
                break;

            case 1: // '\001'
                size = 3 + readUnsignedShort(index + 1);
                if(size > max)
                    max = size;
                break;

            case 15: // '\017'
                size = 4;
                break;

            case 2: // '\002'
            case 7: // '\007'
            case 8: // '\b'
            case 13: // '\r'
            case 14: // '\016'
            case 16: // '\020'
            case 17: // '\021'
            default:
                size = 3;
                break;
            }
            index += size;
        }

        maxStringLength = max;
        header = index;
    }

    public int getAccess()
    {
        return readUnsignedShort(header);
    }

    public String getClassName()
    {
        return readClass(header + 2, new char[maxStringLength]);
    }

    public String getSuperName()
    {
        return readClass(header + 4, new char[maxStringLength]);
    }

    public String[] getInterfaces()
    {
        int index = header + 6;
        int n = readUnsignedShort(index);
        String interfaces[] = new String[n];
        if(n > 0)
        {
            char buf[] = new char[maxStringLength];
            for(int i = 0; i < n; i++)
            {
                index += 2;
                interfaces[i] = readClass(index, buf);
            }

        }
        return interfaces;
    }

    void copyPool(ClassWriter classWriter)
    {
        char buf[] = new char[maxStringLength];
        int ll = items.length;
        Item items2[] = new Item[ll];
        for(int i = 1; i < ll; i++)
        {
            int index = items[i];
            int tag = b[index - 1];
            Item item = new Item(i);
            switch(tag)
            {
            case 9: // '\t'
            case 10: // '\n'
            case 11: // '\013'
            {
                int nameType = items[readUnsignedShort(index + 2)];
                item.set(tag, readClass(index, buf), readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
                break;
            }

            case 3: // '\003'
            {
                item.set(readInt(index));
                break;
            }

            case 4: // '\004'
            {
                item.set(Float.intBitsToFloat(readInt(index)));
                break;
            }

            case 12: // '\f'
            {
                item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), null);
                break;
            }

            case 5: // '\005'
            {
                item.set(readLong(index));
                i++;
                break;
            }

            case 6: // '\006'
            {
                item.set(Double.longBitsToDouble(readLong(index)));
                i++;
                break;
            }

            case 1: // '\001'
            {
                String s = strings[i];
                if(s == null)
                {
                    index = items[i];
                    s = strings[i] = readUTF(index + 2, readUnsignedShort(index), buf);
                }
                item.set(tag, s, null, null);
                break;
            }

            case 15: // '\017'
            {
                int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
                int nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
                item.set(20 + readByte(index), readClass(fieldOrMethodRef, buf), readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
                break;
            }

            case 18: // '\022'
            {
                if(classWriter.bootstrapMethods == null)
                    copyBootstrapMethods(classWriter, items2, buf);
                int nameType = items[readUnsignedShort(index + 2)];
                item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), readUnsignedShort(index));
                break;
            }

            case 2: // '\002'
            case 7: // '\007'
            case 8: // '\b'
            case 13: // '\r'
            case 14: // '\016'
            case 16: // '\020'
            case 17: // '\021'
            default:
            {
                item.set(tag, readUTF8(index, buf), null, null);
                break;
            }
            }
            int index2 = item.hashCode % items2.length;
            item.next = items2[index2];
            items2[index2] = item;
        }

        int off = items[1] - 1;
        classWriter.pool.putByteArray(b, off, header - off);
        classWriter.items = items2;
        classWriter.threshold = (int)(0.75D * (double)ll);
        classWriter.index = ll;
    }

    private void copyBootstrapMethods(ClassWriter classWriter, Item items[], char c[])
    {
        int u = getAttributes();
        boolean found = false;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            String attrName = readUTF8(u + 2, c);
            if("BootstrapMethods".equals(attrName))
            {
                found = true;
                break;
            }
            u += 6 + readInt(u + 4);
        }

        if(!found)
            return;
        int boostrapMethodCount = readUnsignedShort(u + 8);
        int j = 0;
        int v = u + 10;
        for(; j < boostrapMethodCount; j++)
        {
            int position = v - u - 10;
            int hashCode = readConst(readUnsignedShort(v), c).hashCode();
            for(int k = readUnsignedShort(v + 2); k > 0; k--)
            {
                hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
                v += 2;
            }

            v += 4;
            Item item = new Item(j);
            item.set(position, hashCode & 0x7fffffff);
            int index = item.hashCode % items.length;
            item.next = items[index];
            items[index] = item;
        }

        int attrSize = readInt(u + 4);
        ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
        bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
        classWriter.bootstrapMethodsCount = boostrapMethodCount;
        classWriter.bootstrapMethods = bootstrapMethods;
    }

    public ClassReader(InputStream is)
        throws IOException
    {
        this(readClass(is, false));
    }

    public ClassReader(String name)
        throws IOException
    {
        this(readClass(ClassLoader.getSystemResourceAsStream((new StringBuilder(String.valueOf(name.replace('.', '/')))).append(".class").toString()), true));
    }

    private static byte[] readClass(InputStream is, boolean close)
        throws IOException
    {
    	byte[]bs =  Util.readByte(is);
    	if(close) {
    		is.close();
    	}
    	return bs;
//        if(is == null)
//            throw new IOException("Class not found");
//        byte b[];
//        int len;
//        b = new byte[is.available()];
//        len = 0;
//_L4:
//        int n = is.read(b, len, b.length - len);
//        if(n != -1) {
//        	 len += n;
//             if(len != b.length) goto _L4; else goto _L3
//        } else goto {
//        	 byte abyte0[];
//             if(len < b.length)
//             {
//                 byte c[] = new byte[len];
//                 System.arraycopy(b, 0, c, 0, len);
//                 b = c;
//             }
//             abyte0 = b;
//             if(close)
//                 is.close();
//             return abyte0;
//        }
//_L1:
//       
//_L2:
//       
//_L3:
//        int last;
//        last = is.read();
//        if(last >= 0)
//            break MISSING_BLOCK_LABEL_115;
//        abyte0 = b;
//        if(close)
//            is.close();
//        return abyte0;
//        byte c[] = new byte[b.length + 1000];
//        System.arraycopy(b, 0, c, 0, len);
//        c[len++] = (byte)last;
//        b = c;
//          goto _L4
//        Exception exception;
//        exception;
//        if(close)
//            is.close();
//        throw exception;
    }

    public void accept(ClassVisitor classVisitor, int flags)
    {
        accept(classVisitor, new Attribute[0], flags);
    }

    public void accept(ClassVisitor classVisitor, Attribute attrs[], int flags)
    {
        int u = header;
        char c[] = new char[maxStringLength];
        Context context = new Context();
        context.attrs = attrs;
        context.flags = flags;
        context.buffer = c;
        int access = readUnsignedShort(u);
        String name = readClass(u + 2, c);
        String superClass = readClass(u + 4, c);
        String interfaces[] = new String[readUnsignedShort(u + 6)];
        u += 8;
        for(int i = 0; i < interfaces.length; i++)
        {
            interfaces[i] = readClass(u, c);
            u += 2;
        }

        String signature = null;
        String sourceFile = null;
        String sourceDebug = null;
        String enclosingOwner = null;
        String enclosingName = null;
        String enclosingDesc = null;
        int anns = 0;
        int ianns = 0;
        int innerClasses = 0;
        Attribute attributes = null;
        u = getAttributes();
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            String attrName = readUTF8(u + 2, c);
            if("SourceFile".equals(attrName))
                sourceFile = readUTF8(u + 8, c);
            else
            if("InnerClasses".equals(attrName))
                innerClasses = u + 8;
            else
            if("EnclosingMethod".equals(attrName))
            {
                enclosingOwner = readClass(u + 8, c);
                int item = readUnsignedShort(u + 10);
                if(item != 0)
                {
                    enclosingName = readUTF8(items[item], c);
                    enclosingDesc = readUTF8(items[item] + 2, c);
                }
            } else
            if("Signature".equals(attrName))
                signature = readUTF8(u + 8, c);
            else
            if("RuntimeVisibleAnnotations".equals(attrName))
                anns = u + 8;
            else
            if("Deprecated".equals(attrName))
                access |= 0x20000;
            else
            if("Synthetic".equals(attrName))
                access |= 0x41000;
            else
            if("SourceDebugExtension".equals(attrName))
            {
                int len = readInt(u + 4);
                sourceDebug = readUTF(u + 8, len, new char[len]);
            } else
            if("RuntimeInvisibleAnnotations".equals(attrName))
                ianns = u + 8;
            else
            if("BootstrapMethods".equals(attrName))
            {
                int bootstrapMethods[] = new int[readUnsignedShort(u + 8)];
                int j = 0;
                int v = u + 10;
                for(; j < bootstrapMethods.length; j++)
                {
                    bootstrapMethods[j] = v;
                    v += 2 + readUnsignedShort(v + 2) << 1;
                }

                context.bootstrapMethods = bootstrapMethods;
            } else
            {
                Attribute attr = readAttribute(attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
                if(attr != null)
                {
                    attr.next = attributes;
                    attributes = attr;
                }
            }
            u += 6 + readInt(u + 4);
        }

        classVisitor.visit(readInt(items[1] - 7), access, name, signature, superClass, interfaces);
        if((flags & 2) == 0 && (sourceFile != null || sourceDebug != null))
            classVisitor.visitSource(sourceFile, sourceDebug);
        if(enclosingOwner != null)
            classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc);
        if(anns != 0)
        {
            int i = readUnsignedShort(anns);
            int v = anns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true));

        }
        if(ianns != 0)
        {
            int i = readUnsignedShort(ianns);
            int v = ianns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false));

        }
        Attribute attr;
        for(; attributes != null; attributes = attr)
        {
            attr = attributes.next;
            attributes.next = null;
            classVisitor.visitAttribute(attributes);
        }

        if(innerClasses != 0)
        {
            int v = innerClasses + 2;
            for(int i = readUnsignedShort(innerClasses); i > 0; i--)
            {
                classVisitor.visitInnerClass(readClass(v, c), readClass(v + 2, c), readUTF8(v + 4, c), readUnsignedShort(v + 6));
                v += 8;
            }

        }
        u = header + 10 + 2 * interfaces.length;
        for(int i = readUnsignedShort(u - 2); i > 0; i--)
            u = readField(classVisitor, context, u);

        u += 2;
        for(int i = readUnsignedShort(u - 2); i > 0; i--)
            u = readMethod(classVisitor, context, u);

        classVisitor.visitEnd();
    }

    private int readField(ClassVisitor classVisitor, Context context, int u)
    {
        char c[] = context.buffer;
        int access = readUnsignedShort(u);
        String name = readUTF8(u + 2, c);
        String desc = readUTF8(u + 4, c);
        u += 6;
        String signature = null;
        int anns = 0;
        int ianns = 0;
        Object value = null;
        Attribute attributes = null;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            String attrName = readUTF8(u + 2, c);
            if("ConstantValue".equals(attrName))
            {
                int item = readUnsignedShort(u + 8);
                value = item != 0 ? readConst(item, c) : null;
            } else
            if("Signature".equals(attrName))
                signature = readUTF8(u + 8, c);
            else
            if("Deprecated".equals(attrName))
                access |= 0x20000;
            else
            if("Synthetic".equals(attrName))
                access |= 0x41000;
            else
            if("RuntimeVisibleAnnotations".equals(attrName))
                anns = u + 8;
            else
            if("RuntimeInvisibleAnnotations".equals(attrName))
            {
                ianns = u + 8;
            } else
            {
                Attribute attr = readAttribute(context.attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
                if(attr != null)
                {
                    attr.next = attributes;
                    attributes = attr;
                }
            }
            u += 6 + readInt(u + 4);
        }

        u += 2;
        FieldVisitor fv = classVisitor.visitField(access, name, desc, signature, value);
        if(fv == null)
            return u;
        if(anns != 0)
        {
            int i = readUnsignedShort(anns);
            int v = anns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), true));

        }
        if(ianns != 0)
        {
            int i = readUnsignedShort(ianns);
            int v = ianns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, fv.visitAnnotation(readUTF8(v, c), false));

        }
        Attribute attr;
        for(; attributes != null; attributes = attr)
        {
            attr = attributes.next;
            attributes.next = null;
            fv.visitAttribute(attributes);
        }

        fv.visitEnd();
        return u;
    }

    private int readMethod(ClassVisitor classVisitor, Context context, int u)
    {
        char c[] = context.buffer;
        int access = readUnsignedShort(u);
        String name = readUTF8(u + 2, c);
        String desc = readUTF8(u + 4, c);
        u += 6;
        int code = 0;
        int exception = 0;
        String exceptions[] = (String[])null;
        String signature = null;
        int anns = 0;
        int ianns = 0;
        int dann = 0;
        int mpanns = 0;
        int impanns = 0;
        int firstAttribute = u;
        Attribute attributes = null;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            String attrName = readUTF8(u + 2, c);
            if("Code".equals(attrName))
            {
                if((context.flags & 1) == 0)
                    code = u + 8;
            } else
            if("Exceptions".equals(attrName))
            {
                exceptions = new String[readUnsignedShort(u + 8)];
                exception = u + 10;
                for(int j = 0; j < exceptions.length; j++)
                {
                    exceptions[j] = readClass(exception, c);
                    exception += 2;
                }

            } else
            if("Signature".equals(attrName))
                signature = readUTF8(u + 8, c);
            else
            if("Deprecated".equals(attrName))
                access |= 0x20000;
            else
            if("RuntimeVisibleAnnotations".equals(attrName))
                anns = u + 8;
            else
            if("AnnotationDefault".equals(attrName))
                dann = u + 8;
            else
            if("Synthetic".equals(attrName))
                access |= 0x41000;
            else
            if("RuntimeInvisibleAnnotations".equals(attrName))
                ianns = u + 8;
            else
            if("RuntimeVisibleParameterAnnotations".equals(attrName))
                mpanns = u + 8;
            else
            if("RuntimeInvisibleParameterAnnotations".equals(attrName))
            {
                impanns = u + 8;
            } else
            {
                Attribute attr = readAttribute(context.attrs, attrName, u + 8, readInt(u + 4), c, -1, null);
                if(attr != null)
                {
                    attr.next = attributes;
                    attributes = attr;
                }
            }
            u += 6 + readInt(u + 4);
        }

        u += 2;
        MethodVisitor mv = classVisitor.visitMethod(access, name, desc, signature, exceptions);
        if(mv == null)
            return u;
        if(mv instanceof MethodWriter)
        {
            MethodWriter mw = (MethodWriter)mv;
            if(mw.cw.cr == this && signature.equals(mw.signature))
            {
                boolean sameExceptions = false;
                if(exceptions == null)
                    sameExceptions = mw.exceptionCount == 0;
                else
                if(exceptions.length == mw.exceptionCount)
                {
                    sameExceptions = true;
                    for(int j = exceptions.length - 1; j >= 0; j--)
                    {
                        exception -= 2;
                        if(mw.exceptions[j] == readUnsignedShort(exception))
                            continue;
                        sameExceptions = false;
                        break;
                    }

                }
                if(sameExceptions)
                {
                    mw.classReaderOffset = firstAttribute;
                    mw.classReaderLength = u - firstAttribute;
                    return u;
                }
            }
        }
        if(dann != 0)
        {
            AnnotationVisitor dv = mv.visitAnnotationDefault();
            readAnnotationValue(dann, c, null, dv);
            if(dv != null)
                dv.visitEnd();
        }
        if(anns != 0)
        {
            int i = readUnsignedShort(anns);
            int v = anns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), true));

        }
        if(ianns != 0)
        {
            int i = readUnsignedShort(ianns);
            int v = ianns + 2;
            for(; i > 0; i--)
                v = readAnnotationValues(v + 2, c, true, mv.visitAnnotation(readUTF8(v, c), false));

        }
        if(mpanns != 0)
            readParameterAnnotations(mpanns, desc, c, true, mv);
        if(impanns != 0)
            readParameterAnnotations(impanns, desc, c, false, mv);
        Attribute attr;
        for(; attributes != null; attributes = attr)
        {
            attr = attributes.next;
            attributes.next = null;
            mv.visitAttribute(attributes);
        }

        if(code != 0)
        {
            context.access = access;
            context.name = name;
            context.desc = desc;
            mv.visitCode();
            readCode(mv, context, code);
        }
        mv.visitEnd();
        return u;
    }

    private void readCode(MethodVisitor mv, Context context, int u)
    {
        byte b[] = this.b;
        char c[] = context.buffer;
        int maxStack = readUnsignedShort(u);
        int maxLocals = readUnsignedShort(u + 2);
        int codeLength = readInt(u + 4);
        int codeStart = u += 8;
        int codeEnd = u + codeLength;
        Label labels[] = new Label[codeLength + 2];
        readLabel(codeLength + 1, labels);
        while(u < codeEnd) 
        {
            int offset = u - codeStart;
            int opcode = b[u] & 0xff;
            switch(ClassWriter.TYPE[opcode])
            {
            case 0: // '\0'
            case 4: // '\004'
                u++;
                break;

            case 9: // '\t'
                readLabel(offset + readShort(u + 1), labels);
                u += 3;
                break;

            case 10: // '\n'
                readLabel(offset + readInt(u + 1), labels);
                u += 5;
                break;

            case 17: // '\021'
                opcode = b[u + 1] & 0xff;
                if(opcode == 132)
                    u += 6;
                else
                    u += 4;
                break;

            case 14: // '\016'
                u = (u + 4) - (offset & 3);
                readLabel(offset + readInt(u), labels);
                for(int i = (readInt(u + 8) - readInt(u + 4)) + 1; i > 0; i--)
                {
                    readLabel(offset + readInt(u + 12), labels);
                    u += 4;
                }

                u += 12;
                break;

            case 15: // '\017'
                u = (u + 4) - (offset & 3);
                readLabel(offset + readInt(u), labels);
                for(int i = readInt(u + 4); i > 0; i--)
                {
                    readLabel(offset + readInt(u + 12), labels);
                    u += 8;
                }

                u += 8;
                break;

            case 1: // '\001'
            case 3: // '\003'
            case 11: // '\013'
                u += 2;
                break;

            case 2: // '\002'
            case 5: // '\005'
            case 6: // '\006'
            case 12: // '\f'
            case 13: // '\r'
                u += 3;
                break;

            case 7: // '\007'
            case 8: // '\b'
                u += 5;
                break;

            case 16: // '\020'
            default:
                u += 4;
                break;
            }
        }
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            Label start = readLabel(readUnsignedShort(u + 2), labels);
            Label end = readLabel(readUnsignedShort(u + 4), labels);
            Label handler = readLabel(readUnsignedShort(u + 6), labels);
            String type = readUTF8(items[readUnsignedShort(u + 8)], c);
            mv.visitTryCatchBlock(start, end, handler, type);
            u += 8;
        }

        u += 2;
        int varTable = 0;
        int varTypeTable = 0;
        boolean zip = true;
        boolean unzip = (context.flags & 8) != 0;
        int stackMap = 0;
        int stackMapSize = 0;
        int frameCount = 0;
        Context frame = null;
        Attribute attributes = null;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            String attrName = readUTF8(u + 2, c);
            if("LocalVariableTable".equals(attrName))
            {
                if((context.flags & 2) == 0)
                {
                    varTable = u + 8;
                    int j = readUnsignedShort(u + 8);
                    int v = u;
                    for(; j > 0; j--)
                    {
                        int label = readUnsignedShort(v + 10);
                        if(labels[label] == null)
                            readLabel(label, labels).status |= 1;
                        label += readUnsignedShort(v + 12);
                        if(labels[label] == null)
                            readLabel(label, labels).status |= 1;
                        v += 10;
                    }

                }
            } else
            if("LocalVariableTypeTable".equals(attrName))
                varTypeTable = u + 8;
            else
            if("LineNumberTable".equals(attrName))
            {
                if((context.flags & 2) == 0)
                {
                    int j = readUnsignedShort(u + 8);
                    int v = u;
                    for(; j > 0; j--)
                    {
                        int label = readUnsignedShort(v + 10);
                        if(labels[label] == null)
                            readLabel(label, labels).status |= 1;
                        labels[label].line = readUnsignedShort(v + 12);
                        v += 4;
                    }

                }
            } else
            if("StackMapTable".equals(attrName))
            {
                if((context.flags & 4) == 0)
                {
                    stackMap = u + 10;
                    stackMapSize = readInt(u + 4);
                    frameCount = readUnsignedShort(u + 8);
                }
            } else
            if("StackMap".equals(attrName))
            {
                if((context.flags & 4) == 0)
                {
                    zip = false;
                    stackMap = u + 10;
                    stackMapSize = readInt(u + 4);
                    frameCount = readUnsignedShort(u + 8);
                }
            } else
            {
                for(int j = 0; j < context.attrs.length; j++)
                    if(context.attrs[j].type.equals(attrName))
                    {
                        Attribute attr = context.attrs[j].read(this, u + 8, readInt(u + 4), c, codeStart - 8, labels);
                        if(attr != null)
                        {
                            attr.next = attributes;
                            attributes = attr;
                        }
                    }

            }
            u += 6 + readInt(u + 4);
        }

        u += 2;
        if(stackMap != 0)
        {
            frame = context;
            frame.offset = -1;
            frame.mode = 0;
            frame.localCount = 0;
            frame.localDiff = 0;
            frame.stackCount = 0;
            frame.local = new Object[maxLocals];
            frame.stack = new Object[maxStack];
            if(unzip)
                getImplicitFrame(context);
            for(int i = stackMap; i < (stackMap + stackMapSize) - 2; i++)
                if(b[i] == 8)
                {
                    int v = readUnsignedShort(i + 1);
                    if(v >= 0 && v < codeLength && (b[codeStart + v] & 0xff) == 187)
                        readLabel(v, labels);
                }

        }
        for(u = codeStart; u < codeEnd;)
        {
            int offset = u - codeStart;
            Label l = labels[offset];
            if(l != null)
            {
                mv.visitLabel(l);
                if((context.flags & 2) == 0 && l.line > 0)
                    mv.visitLineNumber(l.line, l);
            }
            while(frame != null && (frame.offset == offset || frame.offset == -1)) 
            {
                if(frame.offset != -1)
                    if(!zip || unzip)
                        mv.visitFrame(-1, frame.localCount, frame.local, frame.stackCount, frame.stack);
                    else
                        mv.visitFrame(frame.mode, frame.localDiff, frame.local, frame.stackCount, frame.stack);
                if(frameCount > 0)
                {
                    stackMap = readFrame(stackMap, zip, unzip, labels, frame);
                    frameCount--;
                } else
                {
                    frame = null;
                }
            }
            int opcode = b[u] & 0xff;
            switch(ClassWriter.TYPE[opcode])
            {
            case 0: // '\0'
            {
                mv.visitInsn(opcode);
                u++;
                break;
            }

            case 4: // '\004'
            {
                if(opcode > 54)
                {
                    opcode -= 59;
                    mv.visitVarInsn(54 + (opcode >> 2), opcode & 3);
                } else
                {
                    opcode -= 26;
                    mv.visitVarInsn(21 + (opcode >> 2), opcode & 3);
                }
                u++;
                break;
            }

            case 9: // '\t'
            {
                mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
                u += 3;
                break;
            }

            case 10: // '\n'
            {
                mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
                u += 5;
                break;
            }

            case 17: // '\021'
            {
                opcode = b[u + 1] & 0xff;
                if(opcode == 132)
                {
                    mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
                    u += 6;
                } else
                {
                    mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
                    u += 4;
                }
                break;
            }

            case 14: // '\016'
            {
                u = (u + 4) - (offset & 3);
                int label = offset + readInt(u);
                int min = readInt(u + 4);
                int max = readInt(u + 8);
                Label table[] = new Label[(max - min) + 1];
                u += 12;
                for(int i = 0; i < table.length; i++)
                {
                    table[i] = labels[offset + readInt(u)];
                    u += 4;
                }

                mv.visitTableSwitchInsn(min, max, labels[label], table);
                break;
            }

            case 15: // '\017'
            {
                u = (u + 4) - (offset & 3);
                int label = offset + readInt(u);
                int len = readInt(u + 4);
                int keys[] = new int[len];
                Label values[] = new Label[len];
                u += 8;
                for(int i = 0; i < len; i++)
                {
                    keys[i] = readInt(u);
                    values[i] = labels[offset + readInt(u + 4)];
                    u += 8;
                }

                mv.visitLookupSwitchInsn(labels[label], keys, values);
                break;
            }

            case 3: // '\003'
            {
                mv.visitVarInsn(opcode, b[u + 1] & 0xff);
                u += 2;
                break;
            }

            case 1: // '\001'
            {
                mv.visitIntInsn(opcode, b[u + 1]);
                u += 2;
                break;
            }

            case 2: // '\002'
            {
                mv.visitIntInsn(opcode, readShort(u + 1));
                u += 3;
                break;
            }

            case 11: // '\013'
            {
                mv.visitLdcInsn(readConst(b[u + 1] & 0xff, c));
                u += 2;
                break;
            }

            case 12: // '\f'
            {
                mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
                u += 3;
                break;
            }

            case 6: // '\006'
            case 7: // '\007'
            {
                int cpIndex = items[readUnsignedShort(u + 1)];
                String iowner = readClass(cpIndex, c);
                cpIndex = items[readUnsignedShort(cpIndex + 2)];
                String iname = readUTF8(cpIndex, c);
                String idesc = readUTF8(cpIndex + 2, c);
                if(opcode < 182)
                    mv.visitFieldInsn(opcode, iowner, iname, idesc);
                else
                    mv.visitMethodInsn(opcode, iowner, iname, idesc);
                if(opcode == 185)
                    u += 5;
                else
                    u += 3;
                break;
            }

            case 8: // '\b'
            {
                int cpIndex = items[readUnsignedShort(u + 1)];
                int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
                Handle bsm = (Handle)readConst(readUnsignedShort(bsmIndex), c);
                int bsmArgCount = readUnsignedShort(bsmIndex + 2);
                Object bsmArgs[] = new Object[bsmArgCount];
                bsmIndex += 4;
                for(int i = 0; i < bsmArgCount; i++)
                {
                    bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
                    bsmIndex += 2;
                }

                cpIndex = items[readUnsignedShort(cpIndex + 2)];
                String iname = readUTF8(cpIndex, c);
                String idesc = readUTF8(cpIndex + 2, c);
                mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
                u += 5;
                break;
            }

            case 5: // '\005'
            {
                mv.visitTypeInsn(opcode, readClass(u + 1, c));
                u += 3;
                break;
            }

            case 13: // '\r'
            {
                mv.visitIincInsn(b[u + 1] & 0xff, b[u + 2]);
                u += 3;
                break;
            }

            case 16: // '\020'
            default:
            {
                mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xff);
                u += 4;
                break;
            }
            }
        }

        if(labels[codeLength] != null)
            mv.visitLabel(labels[codeLength]);
        if((context.flags & 2) == 0 && varTable != 0)
        {
            int typeTable[] = (int[])null;
            if(varTypeTable != 0)
            {
                u = varTypeTable + 2;
                typeTable = new int[readUnsignedShort(varTypeTable) * 3];
                for(int i = typeTable.length; i > 0;)
                {
                    typeTable[--i] = u + 6;
                    typeTable[--i] = readUnsignedShort(u + 8);
                    typeTable[--i] = readUnsignedShort(u);
                    u += 10;
                }

            }
            u = varTable + 2;
            for(int i = readUnsignedShort(varTable); i > 0; i--)
            {
                int start = readUnsignedShort(u);
                int length = readUnsignedShort(u + 2);
                int index = readUnsignedShort(u + 8);
                String vsignature = null;
                if(typeTable != null)
                {
                    for(int j = 0; j < typeTable.length; j += 3)
                    {
                        if(typeTable[j] != start || typeTable[j + 1] != index)
                            continue;
                        vsignature = readUTF8(typeTable[j + 2], c);
                        break;
                    }

                }
                mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), vsignature, labels[start], labels[start + length], index);
                u += 10;
            }

        }
        Attribute attr;
        for(; attributes != null; attributes = attr)
        {
            attr = attributes.next;
            attributes.next = null;
            mv.visitAttribute(attributes);
        }

        mv.visitMaxs(maxStack, maxLocals);
    }

    private void readParameterAnnotations(int v, String desc, char buf[], boolean visible, MethodVisitor mv)
    {
        int n = b[v++] & 0xff;
        int synthetics = Type.getArgumentTypes(desc).length - n;
        int i;
        for(i = 0; i < synthetics; i++)
        {
            AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
            if(av != null)
                av.visitEnd();
        }

        for(; i < n + synthetics; i++)
        {
            int j = readUnsignedShort(v);
            v += 2;
            for(; j > 0; j--)
            {
                AnnotationVisitor av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
                v = readAnnotationValues(v + 2, buf, true, av);
            }

        }

    }

    private int readAnnotationValues(int v, char buf[], boolean named, AnnotationVisitor av)
    {
        int i = readUnsignedShort(v);
        v += 2;
        if(named)
            for(; i > 0; i--)
                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);

        else
            for(; i > 0; i--)
                v = readAnnotationValue(v, buf, null, av);

        if(av != null)
            av.visitEnd();
        return v;
    }

    private int readAnnotationValue(int v, char buf[], String name, AnnotationVisitor av)
    {
        if(av == null)
        {
            switch(b[v] & 0xff)
            {
            case 101: // 'e'
                return v + 5;

            case 64: // '@'
                return readAnnotationValues(v + 3, buf, true, null);

            case 91: // '['
                return readAnnotationValues(v + 1, buf, false, null);
            }
            return v + 3;
        }
label0:
        switch(b[v++] & 0xff)
        {
        default:
            break;

        case 68: // 'D'
        case 70: // 'F'
        case 73: // 'I'
        case 74: // 'J'
            av.visit(name, readConst(readUnsignedShort(v), buf));
            v += 2;
            break;

        case 66: // 'B'
            av.visit(name, new Byte((byte)readInt(items[readUnsignedShort(v)])));
            v += 2;
            break;

        case 90: // 'Z'
            av.visit(name, readInt(items[readUnsignedShort(v)]) != 0 ? ((Object) (Boolean.TRUE)) : ((Object) (Boolean.FALSE)));
            v += 2;
            break;

        case 83: // 'S'
            av.visit(name, new Short((short)readInt(items[readUnsignedShort(v)])));
            v += 2;
            break;

        case 67: // 'C'
            av.visit(name, new Character((char)readInt(items[readUnsignedShort(v)])));
            v += 2;
            break;

        case 115: // 's'
            av.visit(name, readUTF8(v, buf));
            v += 2;
            break;

        case 101: // 'e'
            av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
            v += 4;
            break;

        case 99: // 'c'
            av.visit(name, Type.getType(readUTF8(v, buf)));
            v += 2;
            break;

        case 64: // '@'
            v = readAnnotationValues(v + 2, buf, true, av.visitAnnotation(name, readUTF8(v, buf)));
            break;

        case 91: // '['
            int size = readUnsignedShort(v);
            v += 2;
            if(size == 0)
                return readAnnotationValues(v - 2, buf, false, av.visitArray(name));
            switch(b[v++] & 0xff)
            {
            case 66: // 'B'
                byte bv[] = new byte[size];
                for(int i = 0; i < size; i++)
                {
                    bv[i] = (byte)readInt(items[readUnsignedShort(v)]);
                    v += 3;
                }

                av.visit(name, bv);
                v--;
                break label0;

            case 90: // 'Z'
                boolean zv[] = new boolean[size];
                for(int i = 0; i < size; i++)
                {
                    zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
                    v += 3;
                }

                av.visit(name, zv);
                v--;
                break label0;

            case 83: // 'S'
                short sv[] = new short[size];
                for(int i = 0; i < size; i++)
                {
                    sv[i] = (short)readInt(items[readUnsignedShort(v)]);
                    v += 3;
                }

                av.visit(name, sv);
                v--;
                break label0;

            case 67: // 'C'
                char cv[] = new char[size];
                for(int i = 0; i < size; i++)
                {
                    cv[i] = (char)readInt(items[readUnsignedShort(v)]);
                    v += 3;
                }

                av.visit(name, cv);
                v--;
                break label0;

            case 73: // 'I'
                int iv[] = new int[size];
                for(int i = 0; i < size; i++)
                {
                    iv[i] = readInt(items[readUnsignedShort(v)]);
                    v += 3;
                }

                av.visit(name, iv);
                v--;
                break label0;

            case 74: // 'J'
                long lv[] = new long[size];
                for(int i = 0; i < size; i++)
                {
                    lv[i] = readLong(items[readUnsignedShort(v)]);
                    v += 3;
                }

                av.visit(name, lv);
                v--;
                break label0;

            case 70: // 'F'
                float fv[] = new float[size];
                for(int i = 0; i < size; i++)
                {
                    fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
                    v += 3;
                }

                av.visit(name, fv);
                v--;
                break label0;

            case 68: // 'D'
                double dv[] = new double[size];
                for(int i = 0; i < size; i++)
                {
                    dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
                    v += 3;
                }

                av.visit(name, dv);
                v--;
                break;

            default:
                v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
                break;
            }
            break;
        }
        return v;
    }

    private void getImplicitFrame(Context frame)
    {
        String desc = frame.desc;
        Object locals[] = frame.local;
        int local = 0;
        if((frame.access & 8) == 0)
            if("".equals(frame.name))
                locals[local++] = Opcodes.UNINITIALIZED_THIS;
            else
                locals[local++] = readClass(header + 2, frame.buffer);
        int i = 1;
        do
        {
            int j = i;
            switch(desc.charAt(i++))
            {
            case 66: // 'B'
            case 67: // 'C'
            case 73: // 'I'
            case 83: // 'S'
            case 90: // 'Z'
                locals[local++] = Opcodes.INTEGER;
                break;

            case 70: // 'F'
                locals[local++] = Opcodes.FLOAT;
                break;

            case 74: // 'J'
                locals[local++] = Opcodes.LONG;
                break;

            case 68: // 'D'
                locals[local++] = Opcodes.DOUBLE;
                break;

            case 91: // '['
                for(; desc.charAt(i) == '['; i++);
                if(desc.charAt(i) == 'L')
                    for(i++; desc.charAt(i) != ';'; i++);
                locals[local++] = desc.substring(j, ++i);
                break;

            case 76: // 'L'
                for(; desc.charAt(i) != ';'; i++);
                locals[local++] = desc.substring(j + 1, i++);
                break;

            default:
                frame.localCount = local;
                return;
            }
        } while(true);
    }

    private int readFrame(int stackMap, boolean zip, boolean unzip, Label labels[], Context frame)
    {
        char c[] = frame.buffer;
        int tag;
        if(zip)
        {
            tag = b[stackMap++] & 0xff;
        } else
        {
            tag = 255;
            frame.offset = -1;
        }
        frame.localDiff = 0;
        int delta;
        if(tag < 64)
        {
            delta = tag;
            frame.mode = 3;
            frame.stackCount = 0;
        } else
        if(tag < 128)
        {
            delta = tag - 64;
            stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
            frame.mode = 4;
            frame.stackCount = 1;
        } else
        {
            delta = readUnsignedShort(stackMap);
            stackMap += 2;
            if(tag == 247)
            {
                stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
                frame.mode = 4;
                frame.stackCount = 1;
            } else
            if(tag >= 248 && tag < 251)
            {
                frame.mode = 2;
                frame.localDiff = 251 - tag;
                frame.localCount -= frame.localDiff;
                frame.stackCount = 0;
            } else
            if(tag == 251)
            {
                frame.mode = 3;
                frame.stackCount = 0;
            } else
            if(tag < 255)
            {
                int local = unzip ? frame.localCount : 0;
                for(int i = tag - 251; i > 0; i--)
                    stackMap = readFrameType(frame.local, local++, stackMap, c, labels);

                frame.mode = 1;
                frame.localDiff = tag - 251;
                frame.localCount += frame.localDiff;
                frame.stackCount = 0;
            } else
            {
                frame.mode = 0;
                int n = readUnsignedShort(stackMap);
                stackMap += 2;
                frame.localDiff = n;
                frame.localCount = n;
                int local = 0;
                for(; n > 0; n--)
                    stackMap = readFrameType(frame.local, local++, stackMap, c, labels);

                n = readUnsignedShort(stackMap);
                stackMap += 2;
                frame.stackCount = n;
                int stack = 0;
                for(; n > 0; n--)
                    stackMap = readFrameType(frame.stack, stack++, stackMap, c, labels);

            }
        }
        frame.offset += delta + 1;
        readLabel(frame.offset, labels);
        return stackMap;
    }

    private int readFrameType(Object frame[], int index, int v, char buf[], Label labels[])
    {
        int type = b[v++] & 0xff;
        switch(type)
        {
        case 0: // '\0'
            frame[index] = Opcodes.TOP;
            break;

        case 1: // '\001'
            frame[index] = Opcodes.INTEGER;
            break;

        case 2: // '\002'
            frame[index] = Opcodes.FLOAT;
            break;

        case 3: // '\003'
            frame[index] = Opcodes.DOUBLE;
            break;

        case 4: // '\004'
            frame[index] = Opcodes.LONG;
            break;

        case 5: // '\005'
            frame[index] = Opcodes.NULL;
            break;

        case 6: // '\006'
            frame[index] = Opcodes.UNINITIALIZED_THIS;
            break;

        case 7: // '\007'
            frame[index] = readClass(v, buf);
            v += 2;
            break;

        default:
            frame[index] = readLabel(readUnsignedShort(v), labels);
            v += 2;
            break;
        }
        return v;
    }

    protected Label readLabel(int offset, Label labels[])
    {
        if(labels[offset] == null)
            labels[offset] = new Label();
        return labels[offset];
    }

    private int getAttributes()
    {
        int u = header + 8 + readUnsignedShort(header + 6) * 2;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            for(int j = readUnsignedShort(u + 8); j > 0; j--)
                u += 6 + readInt(u + 12);

            u += 8;
        }

        u += 2;
        for(int i = readUnsignedShort(u); i > 0; i--)
        {
            for(int j = readUnsignedShort(u + 8); j > 0; j--)
                u += 6 + readInt(u + 12);

            u += 8;
        }

        return u + 2;
    }

    private Attribute readAttribute(Attribute attrs[], String type, int off, int len, char buf[], int codeOff, Label labels[])
    {
        for(int i = 0; i < attrs.length; i++)
            if(attrs[i].type.equals(type))
                return attrs[i].read(this, off, len, buf, codeOff, labels);

        return (new Attribute(type)).read(this, off, len, null, -1, null);
    }

    public int getItemCount()
    {
        return items.length;
    }

    public int getItem(int item)
    {
        return items[item];
    }

    public int getMaxStringLength()
    {
        return maxStringLength;
    }

    public int readByte(int index)
    {
        return b[index] & 0xff;
    }

    public int readUnsignedShort(int index)
    {
        byte b[] = this.b;
        return (b[index] & 0xff) << 8 | b[index + 1] & 0xff;
    }

    public short readShort(int index)
    {
        byte b[] = this.b;
        return (short)((b[index] & 0xff) << 8 | b[index + 1] & 0xff);
    }

    public int readInt(int index)
    {
        byte b[] = this.b;
        return (b[index] & 0xff) << 24 | (b[index + 1] & 0xff) << 16 | (b[index + 2] & 0xff) << 8 | b[index + 3] & 0xff;
    }

    public long readLong(int index)
    {
        long l1 = readInt(index);
        long l0 = (long)readInt(index + 4) & 0xffffffffL;
        return l1 << 32 | l0;
    }

    public String readUTF8(int index, char buf[])
    {
        int item = readUnsignedShort(index);
        if(index == 0 || item == 0)
            return null;
        String s = strings[item];
        if(s != null)
        {
            return s;
        } else
        {
            index = items[item];
            return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
        }
    }

    private String readUTF(int index, int utfLen, char buf[])
    {
        int endIndex = index + utfLen;
        byte b[] = this.b;
        int strLen = 0;
        int st = 0;
        char cc = '\0';
        while(index < endIndex) 
        {
            int c = b[index++];
            switch(st)
            {
            default:
                break;

            case 0: // '\0'
                c &= 0xff;
                if(c < 128)
                {
                    buf[strLen++] = (char)c;
                    break;
                }
                if(c < 224 && c > 191)
                {
                    cc = (char)(c & 0x1f);
                    st = 1;
                } else
                {
                    cc = (char)(c & 0xf);
                    st = 2;
                }
                break;

            case 1: // '\001'
                buf[strLen++] = (char)(cc << 6 | c & 0x3f);
                st = 0;
                break;

            case 2: // '\002'
                cc = (char)(cc << 6 | c & 0x3f);
                st = 1;
                break;
            }
        }
        return new String(buf, 0, strLen);
    }

    public String readClass(int index, char buf[])
    {
        return readUTF8(items[readUnsignedShort(index)], buf);
    }

    public Object readConst(int item, char buf[])
    {
        int index = this.items[item];
        switch(b[index - 1])
        {
        case 3: // '\003'
            return new Integer(readInt(index));

        case 4: // '\004'
            return new Float(Float.intBitsToFloat(readInt(index)));

        case 5: // '\005'
            return new Long(readLong(index));

        case 6: // '\006'
            return new Double(Double.longBitsToDouble(readLong(index)));

        case 7: // '\007'
            return Type.getObjectType(readUTF8(index, buf));

        case 8: // '\b'
            return readUTF8(index, buf);

        case 16: // '\020'
            return Type.getMethodType(readUTF8(index, buf));

        case 9: // '\t'
        case 10: // '\n'
        case 11: // '\013'
        case 12: // '\f'
        case 13: // '\r'
        case 14: // '\016'
        case 15: // '\017'
        default:
            int tag = readByte(index);
            int items[] = this.items;
            int cpIndex = items[readUnsignedShort(index + 1)];
            String owner = readClass(cpIndex, buf);
            cpIndex = items[readUnsignedShort(cpIndex + 2)];
            String name = readUTF8(cpIndex, buf);
            String desc = readUTF8(cpIndex + 2, buf);
            return new Handle(tag, owner, name, desc);
        }
    }

    public static final int SKIP_CODE = 1;
    public static final int SKIP_DEBUG = 2;
    public static final int SKIP_FRAMES = 4;
    public final int header;
    static final boolean SIGNATURES = true;
    static final boolean ANNOTATIONS = true;
    static final boolean FRAMES = true;
    static final boolean WRITER = true;
    static final boolean RESIZE = true;
    public static final int EXPAND_FRAMES = 8;
    public final byte b[];
    private final int items[];
    private final String strings[];
    private final int maxStringLength;
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy