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

com.tangosol.dev.disassembler.Method Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.dev.disassembler;

import com.tangosol.dev.compiler.java.*;
import com.tangosol.util.*;
import java.io.*;

public class Method extends Member
    {
    private int m_iClass;

    public static Method[] readMethods(DataInput stream, Constant[] aconst, int iClass)
            throws IOException
        {
        int cMethods = stream.readUnsignedShort();
        Method[] aMethods = new Method[cMethods];
        for (int i = 0; i < cMethods; ++i)
            {
            aMethods[i] = new Method(stream, aconst, iClass);
            }
        return aMethods;
        }

    public Method(DataInput stream, Constant[] aconst, int iClass)
            throws IOException
        {
        super(stream, aconst);
        m_iClass = iClass;
        }

    public String[] getParameters()
        {
        return getParameters(getSignature());
        }

    public String getActualDeclaration()
        {
        StringBuffer sb = new StringBuffer();

        String[] asSig   = getParameters();
        sb.append(getType(asSig[0]))
          .append(' ')
          .append(getName())
          .append('(');

        int c = asSig.length;
        for (int i = 1; i < c; ++i)
            {
            if (i > 1)
                {
                sb.append(", ");
                }
            sb.append(getType(asSig[i]));
            }

        sb.append(')');

        return sb.toString();
        }

    public String getDeclaration()
        {
        String sName = getName();
        if (sName.equals(""))
            {
            StringBuffer sb = new StringBuffer();
            sb.append(((ClassConstant) m_aconst[m_iClass]).getSimpleName())
              .append('(');

            String[] asSig = getParameters();
            int c = asSig.length;
            for (int i = 1; i < c; ++i)
                {
                if (i > 1)
                    {
                    sb.append(", ");
                    }
                sb.append(getType(asSig[i]));
                }

            sb.append(')');
            return sb.toString();
            }
        else if (sName.equals(""))
            {
            return isStatic() ? "" : "";
            }
        else
            {
            return getActualDeclaration();
            }
        }

    public String[] getThrows()
        {
        Attribute attr = getAttribute("Exceptions");
        if (attr == null)
            {
            return null;
            }

        try
            {
            DataInput stream = new DataInputStream(
                    new ByteArrayInputStream(attr.getInfo()));

            int c = stream.readUnsignedShort();
            String[] as = new String[c];
            for (int i = 0; i < c; ++i)
                {
                as[i] = ((ClassConstant) m_aconst[stream.readUnsignedShort()]).getName();
                }

            return as;
            }
        catch (IOException e)
            {
            throw new RuntimeException("Illegal \"Exceptions\" Attribute structure.  (" + e.toString() + ")");
            }
        }

    public String toString()
        {
        StringBuffer sb = new StringBuffer(super.toString(ACC_METHOD));
        if (sb.length() > 0)
            {
            sb.append(' ');
            }

        sb.append(getDeclaration());

        return sb.toString();
        }

    public void dump(PrintWriter out, String sBaseIndent)
        {
        String sPkg    = ((ClassConstant) m_aconst[m_iClass]).getPackageName();
        String sIndent = "    ";

        out.print(sBaseIndent + toString());

        String[] asThrows = getThrows();
        if (asThrows != null && asThrows.length > 0)
            {
            String sThrowsIndent = sBaseIndent + sIndent + sIndent;
            int c = asThrows.length;
            for (int i = 0; i < c; ++i)
                {
                // if in this package, strip package name
                String sThrows = asThrows[i];
                if (sThrows.startsWith(sPkg) && sThrows.lastIndexOf('.') == sPkg.length())
                    {
                    sThrows = sThrows.substring(sPkg.length() + 1);
                    }

                if (i == 0)
                    {
                    out.println();
                    out.print(sThrowsIndent + "throws " + sThrows);
                    }
                else
                    {
                    out.println(',');
                    out.print(sThrowsIndent + "       " + sThrows);
                    }
                }
            }

        if (isAbstract())
            {
            out.println(';');
            }
        else
            {
            String sCodeIndent = sBaseIndent + sIndent;
            out.println();
            out.println(sCodeIndent + '{');
            dumpCode(out, sCodeIndent);
            out.println(sCodeIndent + '}');
            }
        }

    public void dumpCode(PrintWriter out, String sIndent)
        {
        if (isNative())
            {
            out.println(sIndent + "");
            return;
            }

        Attribute attr   = getAttribute("Code");
        byte[]    abInfo = attr.getInfo();
        int       cbInfo = abInfo.length;

        try
            {
            // parse header stuff
            DataInput stream = new DataInputStream(
                    new ByteArrayInputStream(abInfo));

            out.println(sIndent + "#pragma max_stack " + stream.readUnsignedShort());
            out.println(sIndent + "#pragma max_locals " + stream.readUnsignedShort());

            // from VM Spec 4.7.4 Code_attribute structure
            int ofCode = 8;
            int cbCode = stream.readInt();

            // calculate number of digits required to show code offset
            int cHexDigits = 0;
            int cDecDigits = 0;

            int cbTemp = cbCode - 1;
            do
                {
                cHexDigits += 2;
                cbTemp     /= 0x100;
                }
            while (cbTemp > 0);

            cbTemp = cbCode - 1;
            do
                {
                cDecDigits += 1;
                cbTemp     /= 10;
                }
            while (cbTemp > 0);
            cDecDigits = Math.max(cDecDigits, 2);

            // set up header formatting for each line of output
            // "[dddd/xxxx] xx xx xx xx  "
            int    cchHead = cDecDigits + cHexDigits + 17;
            char[] achHead = new char[cchHead];

            for (int i = 0; i < cchHead; ++i)
                {
                achHead[i] = ' ';
                }

            achHead[0                          ] = '[';
            achHead[cDecDigits + 1             ] = '/';
            achHead[cDecDigits + cHexDigits + 2] = ']';

            // set up other formatting
            String sFill = "                         "; // 25 spaces
            String sTab  = "  ";                        // "tab" before notes

            // create a new stream just for reading the opcodes
            MarkedByteArrayInputStream streamRaw =
                    new MarkedByteArrayInputStream(abInfo, ofCode, cbCode);
            stream = new DataInputStream(streamRaw);

            // support for "multi-line" _switch opcodes
            boolean fSwitch = false;    // true during disassembling of _switch ops
            boolean fTable  = false;    // tableswitch:true, lookupswitch:false
            boolean fDft    = false;    // true if only default value remains
            int     cCases  = 0;        // number of remaining cases
            int     nCase   = 0;        // for tableswitch, the next case value
            int     ofOp    = 0;        // offset of original _switch instruction
            int     ofDft   = 0;        // offset from ofOp to jump to if no match

            while (true)
                {
                String  sParms = null;
                String  sNotes = null;
                String  sName  = null;

                if (fSwitch)
                    {
                    if (fDft || cCases == 0)
                        {
                        sParms = "default:  goto " + (ofOp + ofDft);
                        fSwitch = false;
                        fDft    = false;
                        }
                    else
                        {
                        int n  = (fTable ? nCase++ : stream.readInt());
                        int of = stream.readInt();

                        sParms = "case " + n + ":  goto " + (ofOp + of);

                        if (--cCases == 0)
                            {
                            fDft = true;
                            }
                        }
                    }
                else
                    {
                    int op = stream.readUnsignedByte();

                    sName = OPNAME [op];
                    if (sName == null)
                        {
                        throw new RuntimeException("Illegal byte code (" + op + ") at offset " + streamRaw.getMarkedOffset() + ".");
                        }

                    boolean fWide = (op == WIDE);
                    if (fWide)
                        {
                        op    = stream.readUnsignedByte();
                        sName = sName + ' ' + OPNAME [op];
                        }

                    // some opcodes have parameters
                    switch (op)
                        {
                        case ALOAD:
                        case ASTORE:
                        case DLOAD:
                        case DSTORE:
                        case FLOAD:
                        case FSTORE:
                        case ILOAD:
                        case ISTORE:
                        case LLOAD:
                        case LSTORE:
                        case RET:
                            // one or two byte index of local variable
                            {
                            int n = (fWide ? stream.readUnsignedShort()
                                           : stream.readUnsignedByte() );
                            sParms = Integer.toString(n);
                            }
                            break;

                        case ANEWARRAY:
                        case CHECKCAST:
                        case INSTANCEOF:
                        case NEW:
                            // two byte constant class index
                            {
                            int n = stream.readUnsignedShort();
                            sParms = Integer.toString(n);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case BIPUSH:
                            // one byte value
                            {
                            int n = stream.readUnsignedByte();
                            sParms = Integer.toString(n);
                            sNotes = "(0x" + Integer.toHexString(n) + ")";
                            }
                            break;

                        case GETFIELD:
                        case GETSTATIC:
                        case PUTFIELD:
                        case PUTSTATIC:
                            // two byte constant field ref index
                            {
                            int n = stream.readUnsignedShort();
                            sParms = Integer.toString(n);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case IFEQ:
                        case IFGE:
                        case IFGT:
                        case IFLE:
                        case IFLT:
                        case IFNE:
                        case IFNONNULL:
                        case IFNULL:
                        case IF_ACMPEQ:
                        case IF_ACMPNE:
                        case IF_ICMPEQ:
                        case IF_ICMPGE:
                        case IF_ICMPGT:
                        case IF_ICMPLE:
                        case IF_ICMPLT:
                        case IF_ICMPNE:
                        case GOTO:
                        case JSR:
                            // two byte opcode offset
                            {
                            ofOp    = streamRaw.getMarkedOffset();
                            int n   = stream.readShort();
                            sParms  = Integer.toString(ofOp + n);
                            }
                            break;

                        case GOTO_W:
                        case JSR_W:
                            // four byte opcode offset
                            {
                            ofOp    = streamRaw.getMarkedOffset();
                            int n   = stream.readInt();
                            sParms  = Integer.toString(ofOp + n);
                            }
                            break;

                        case IINC:
                            // one or two byte index of local variable
                            {
                            int v;
                            int n;
                            if (fWide)
                                {
                                v = stream.readUnsignedShort();
                                n = stream.readShort();
                                sNotes = "(0x" + Integer.toHexString(n & 0xFFFF) + ")";
                                }
                            else
                                {
                                v = stream.readUnsignedByte();
                                n = stream.readByte();
                                sNotes = "(0x" + Integer.toHexString(n & 0xFF) + ")";
                                }
                            sParms = Integer.toString(v) + "," + Integer.toString(n);
                            }
                            break;

                        case INVOKEINTERFACE:
                            // two byte interface method ref, one byte arg count,
                            // and one byte (zero)
                            {
                            int n = stream.readUnsignedShort();
                            int c = stream.readUnsignedByte();
                            stream.readUnsignedByte();

                            sParms = Integer.toString(n) + "," + Integer.toString(c);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case INVOKESPECIAL:
                        case INVOKESTATIC:
                        case INVOKEVIRTUAL:
                            // two byte method ref
                            {
                            int n = stream.readUnsignedShort();
                            sParms = Integer.toString(n);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case LDC:
                        case LDC_W:
                        case LDC2_W:
                            // one or two byte index of constant (int, float,
                            // string, long, or double)
                            {
                            int n = (op == LDC ? stream.readUnsignedByte()
                                               : stream.readUnsignedShort());
                            sParms = Integer.toString(n);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case LOOKUPSWITCH:
                            // NOP pad to 4-byte boundary
                            // 4-byte default (no match) offset from lookupswitch instruction
                            // 4-byte cases count
                            // [cases] 4-byte case value
                            //         4-byte offsets from lookupswitch instruction
                            {
                            fSwitch = true;
                            fTable  = false;
                            ofOp    = streamRaw.getMarkedOffset();

                            while ((streamRaw.getCurrentOffset() & 0x03) != 0)
                                {
                                if (stream.readUnsignedByte() != NOP)
                                    {
                                    throw new RuntimeException("lookupswitch not alligned using NOP at " + ofOp);
                                    }
                                }

                            ofDft  = stream.readInt();
                            cCases = stream.readInt();
                            }
                            break;

                        case MULTIANEWARRAY:
                            // two byte index of constant class
                            // one byte number of dimensions
                            {
                            int n = stream.readUnsignedShort();
                            int c = stream.readUnsignedByte();

                            sParms = Integer.toString(n) + "," + Integer.toString(c);
                            sNotes = m_aconst[n].toString();
                            }
                            break;

                        case NEWARRAY:
                            // one byte array type
                            {
                            int n = stream.readUnsignedByte();
                            sParms = Integer.toString(n);
                            switch (n)
                                {
                                case  4: sNotes = "boolean"; break;
                                case  5: sNotes = "char"   ; break;
                                case  6: sNotes = "float"  ; break;
                                case  7: sNotes = "double" ; break;
                                case  8: sNotes = "byte"   ; break;
                                case  9: sNotes = "short"  ; break;
                                case 10: sNotes = "int"    ; break;
                                case 11: sNotes = "long"   ; break;
                                }
                            }
                            break;

                        case SIPUSH:
                            // two byte short value
                            {
                            int n = stream.readShort();
                            sParms = Integer.toString(n);
                            sNotes = "(0x" + Integer.toHexString(n) + ")";
                            }
                            break;

                        case TABLESWITCH:
                            // NOP pad to 4-byte boundary
                            // 4-byte default (no match) offset from tableswitch instruction
                            // 4-byte low value
                            // 4-byte high value
                            // [high-low+1] 4-byte offsets from tableswitch instruction
                            {
                            fSwitch = true;
                            fTable  = true;
                            ofOp    = streamRaw.getMarkedOffset();

                            while ((streamRaw.getCurrentOffset() & 0x03) != 0)
                                {
                                if (stream.readUnsignedByte() != NOP)
                                    {
                                    throw new RuntimeException("tableswitch not alligned using NOP at " + ofOp);
                                    }
                                }

                            ofDft  = stream.readInt();
                            nCase  = stream.readInt();
                            cCases  = stream.readInt() - nCase + 1;
                            }
                            break;
                        }
                    }

                // format header
                int    ofStart = streamRaw.getMarkedOffset();
                int    ofEnd   = streamRaw.getCurrentOffset();
                byte[] abBytes = streamRaw.getMarkedBytes();
                formatOpHeader(achHead, ofStart, cDecDigits, cHexDigits, abBytes, 0);

                // format name, operands, and notes
                String sDisp = (sName == null ? "    " : sName + " ");
                if (sParms != null)
                    {
                    sDisp += sParms;
                    }
                if (sDisp.length() < 25)
                    {
                    sDisp = (sDisp + sFill).substring(0, 25);
                    }
                if (sNotes != null)
                    {
                    sDisp += sTab + sNotes;
                    }

                out.print(sIndent);
                out.print(achHead);
                out.println(sDisp);

                if (abBytes.length > 4)
                    {
                    for (int of = ofStart + 4; of < ofEnd; of += 4)
                        {
                        formatOpHeader(achHead, of, cDecDigits, cHexDigits, abBytes, of - ofStart);
                        out.print(sIndent);
                        out.println(achHead);
                        }
                    }

                if (streamRaw.available() == 0)
                    {
                    break;
                    }
                }
            }
        catch (IOException e)
            {
            out(e);
            throw new RuntimeException("Illegal \"Code\" Attribute structure.  (" + e.toString() + ")");
            }
        }

    /**
    * @param ach         format into this char array
    * @param nOffset     the code offset being displayed
    * @param cDecDigits  the number of digits to display the decimal offset
    * @param cHexDigits  the number of digits to display the hex offset
    * @param ab          the bytes to hex dump (up to 4 bytes dumped)
    * @param ofFirst     the offset into ab to start dumping at
    */
    private void formatOpHeader(char[] ach, int nOffset, int cDecDigits, int cHexDigits, byte[] ab, int iFirst)
        {
        //  0123456789012345678901234
        // "[dddd/xxxx] xx xx xx xx  "

        int of = cDecDigits;
        int n  = nOffset;
        while (of > 0)
            {
            ach[of--] = (char) ('0' + n % 10);
            n /= 10;
            }

        of = cDecDigits + cHexDigits + 1;
        for (int i = 0; i < cHexDigits; ++i)
            {
            ach[of--] = HEX[nOffset & 0x0F];
            nOffset >>= 4;
            }

        of = cDecDigits + cHexDigits + 4;
        int iLast = iFirst + 4;
        int cb = ab.length;
        for (int i = iFirst; i < iLast; ++i)
            {
            if (i >= cb)
                {
                ach[of  ] = ' ';
                ach[of+1] = ' ';
                }
            else
                {
                n = ((int) ab[i]) & 0xFF;
                ach[of  ] = HEX[(n & 0xF0) >> 4];
                ach[of+1] = HEX[(n & 0x0F)     ];
                }
            of += 3;
            }
        }

    /**
    * Hex characters.
    */
    private static final char[] HEX = "0123456789ABCDEF".toCharArray();

    /**
    * opcodes:  enumerated by opcode value.
    */
    public static final int NOP             = 0x00;
    public static final int ACONST_NULL     = 0x01;
    public static final int ICONST_M1       = 0x02;
    public static final int ICONST_0        = 0x03;
    public static final int ICONST_1        = 0x04;
    public static final int ICONST_2        = 0x05;
    public static final int ICONST_3        = 0x06;
    public static final int ICONST_4        = 0x07;
    public static final int ICONST_5        = 0x08;
    public static final int LCONST_0        = 0x09;
    public static final int LCONST_1        = 0x0a;
    public static final int FCONST_0        = 0x0b;
    public static final int FCONST_1        = 0x0c;
    public static final int FCONST_2        = 0x0d;
    public static final int DCONST_0        = 0x0e;
    public static final int DCONST_1        = 0x0f;
    public static final int BIPUSH          = 0x10;
    public static final int SIPUSH          = 0x11;
    public static final int LDC             = 0x12;
    public static final int LDC_W           = 0x13;
    public static final int LDC2_W          = 0x14;
    public static final int ILOAD           = 0x15;
    public static final int LLOAD           = 0x16;
    public static final int FLOAD           = 0x17;
    public static final int DLOAD           = 0x18;
    public static final int ALOAD           = 0x19;
    public static final int ILOAD_0         = 0x1a;
    public static final int ILOAD_1         = 0x1b;
    public static final int ILOAD_2         = 0x1c;
    public static final int ILOAD_3         = 0x1d;
    public static final int LLOAD_0         = 0x1e;
    public static final int LLOAD_1         = 0x1f;
    public static final int LLOAD_2         = 0x20;
    public static final int LLOAD_3         = 0x21;
    public static final int FLOAD_0         = 0x22;
    public static final int FLOAD_1         = 0x23;
    public static final int FLOAD_2         = 0x24;
    public static final int FLOAD_3         = 0x25;
    public static final int DLOAD_0         = 0x26;
    public static final int DLOAD_1         = 0x27;
    public static final int DLOAD_2         = 0x28;
    public static final int DLOAD_3         = 0x29;
    public static final int ALOAD_0         = 0x2a;
    public static final int ALOAD_1         = 0x2b;
    public static final int ALOAD_2         = 0x2c;
    public static final int ALOAD_3         = 0x2d;
    public static final int IALOAD          = 0x2e;
    public static final int LALOAD          = 0x2f;
    public static final int FALOAD          = 0x30;
    public static final int DALOAD          = 0x31;
    public static final int AALOAD          = 0x32;
    public static final int BALOAD          = 0x33;
    public static final int CALOAD          = 0x34;
    public static final int SALOAD          = 0x35;
    public static final int ISTORE          = 0x36;
    public static final int LSTORE          = 0x37;
    public static final int FSTORE          = 0x38;
    public static final int DSTORE          = 0x39;
    public static final int ASTORE          = 0x3a;
    public static final int ISTORE_0        = 0x3b;
    public static final int ISTORE_1        = 0x3c;
    public static final int ISTORE_2        = 0x3d;
    public static final int ISTORE_3        = 0x3e;
    public static final int LSTORE_0        = 0x3f;
    public static final int LSTORE_1        = 0x40;
    public static final int LSTORE_2        = 0x41;
    public static final int LSTORE_3        = 0x42;
    public static final int FSTORE_0        = 0x43;
    public static final int FSTORE_1        = 0x44;
    public static final int FSTORE_2        = 0x45;
    public static final int FSTORE_3        = 0x46;
    public static final int DSTORE_0        = 0x47;
    public static final int DSTORE_1        = 0x48;
    public static final int DSTORE_2        = 0x49;
    public static final int DSTORE_3        = 0x4a;
    public static final int ASTORE_0        = 0x4b;
    public static final int ASTORE_1        = 0x4c;
    public static final int ASTORE_2        = 0x4d;
    public static final int ASTORE_3        = 0x4e;
    public static final int IASTORE         = 0x4f;
    public static final int LASTORE         = 0x50;
    public static final int FASTORE         = 0x51;
    public static final int DASTORE         = 0x52;
    public static final int AASTORE         = 0x53;
    public static final int BASTORE         = 0x54;
    public static final int CASTORE         = 0x55;
    public static final int SASTORE         = 0x56;
    public static final int POP             = 0x57;
    public static final int POP2            = 0x58;
    public static final int DUP             = 0x59;
    public static final int DUP_X1          = 0x5a;
    public static final int DUP_X2          = 0x5b;
    public static final int DUP2            = 0x5c;
    public static final int DUP2_X1         = 0x5d;
    public static final int DUP2_X2         = 0x5e;
    public static final int SWAP            = 0x5f;
    public static final int IADD            = 0x60;
    public static final int LADD            = 0x61;
    public static final int FADD            = 0x62;
    public static final int DADD            = 0x63;
    public static final int ISUB            = 0x64;
    public static final int LSUB            = 0x65;
    public static final int FSUB            = 0x66;
    public static final int DSUB            = 0x67;
    public static final int IMUL            = 0x68;
    public static final int LMUL            = 0x69;
    public static final int FMUL            = 0x6a;
    public static final int DMUL            = 0x6b;
    public static final int IDIV            = 0x6c;
    public static final int LDIV            = 0x6d;
    public static final int FDIV            = 0x6e;
    public static final int DDIV            = 0x6f;
    public static final int IREM            = 0x70;
    public static final int LREM            = 0x71;
    public static final int FREM            = 0x72;
    public static final int DREM            = 0x73;
    public static final int INEG            = 0x74;
    public static final int LNEG            = 0x75;
    public static final int FNEG            = 0x76;
    public static final int DNEG            = 0x77;
    public static final int ISHL            = 0x78;
    public static final int LSHL            = 0x79;
    public static final int ISHR            = 0x7a;
    public static final int LSHR            = 0x7b;
    public static final int IUSHR           = 0x7c;
    public static final int LUSHR           = 0x7d;
    public static final int IAND            = 0x7e;
    public static final int LAND            = 0x7f;
    public static final int IOR             = 0x80;
    public static final int LOR             = 0x81;
    public static final int IXOR            = 0x82;
    public static final int LXOR            = 0x83;
    public static final int IINC            = 0x84;
    public static final int I2L             = 0x85;
    public static final int I2F             = 0x86;
    public static final int I2D             = 0x87;
    public static final int L2I             = 0x88;
    public static final int L2F             = 0x89;
    public static final int L2D             = 0x8a;
    public static final int F2I             = 0x8b;
    public static final int F2L             = 0x8c;
    public static final int F2D             = 0x8d;
    public static final int D2I             = 0x8e;
    public static final int D2L             = 0x8f;
    public static final int D2F             = 0x90;
    public static final int I2B             = 0x91;
    public static final int I2C             = 0x92;
    public static final int I2S             = 0x93;
    public static final int LCMP            = 0x94;
    public static final int FCMPL           = 0x95;
    public static final int FCMPG           = 0x96;
    public static final int DCMPL           = 0x97;
    public static final int DCMPG           = 0x98;
    public static final int IFEQ            = 0x99;
    public static final int IFNE            = 0x9a;
    public static final int IFLT            = 0x9b;
    public static final int IFGE            = 0x9c;
    public static final int IFGT            = 0x9d;
    public static final int IFLE            = 0x9e;
    public static final int IF_ICMPEQ       = 0x9f;
    public static final int IF_ICMPNE       = 0xa0;
    public static final int IF_ICMPLT       = 0xa1;
    public static final int IF_ICMPGE       = 0xa2;
    public static final int IF_ICMPGT       = 0xa3;
    public static final int IF_ICMPLE       = 0xa4;
    public static final int IF_ACMPEQ       = 0xa5;
    public static final int IF_ACMPNE       = 0xa6;
    public static final int GOTO            = 0xa7;
    public static final int JSR             = 0xa8;
    public static final int RET             = 0xa9;
    public static final int TABLESWITCH     = 0xaa;
    public static final int LOOKUPSWITCH    = 0xab;
    public static final int IRETURN         = 0xac;
    public static final int LRETURN         = 0xad;
    public static final int FRETURN         = 0xae;
    public static final int DRETURN         = 0xaf;
    public static final int ARETURN         = 0xb0;
    public static final int RETURN          = 0xb1;
    public static final int GETSTATIC       = 0xb2;
    public static final int PUTSTATIC       = 0xb3;
    public static final int GETFIELD        = 0xb4;
    public static final int PUTFIELD        = 0xb5;
    public static final int INVOKEVIRTUAL   = 0xb6;
    public static final int INVOKESPECIAL   = 0xb7;
    public static final int INVOKESTATIC    = 0xb8;
    public static final int INVOKEINTERFACE = 0xb9;
    public static final int NEW             = 0xbb;
    public static final int NEWARRAY        = 0xbc;
    public static final int ANEWARRAY       = 0xbd;
    public static final int ARRAYLENGTH     = 0xbe;
    public static final int ATHROW          = 0xbf;
    public static final int CHECKCAST       = 0xc0;
    public static final int INSTANCEOF      = 0xc1;
    public static final int MONITORENTER    = 0xc2;
    public static final int MONITOREXIT     = 0xc3;
    public static final int WIDE            = 0xc4;
    public static final int MULTIANEWARRAY  = 0xc5;
    public static final int IFNULL          = 0xc6;
    public static final int IFNONNULL       = 0xc7;
    public static final int GOTO_W          = 0xc8;
    public static final int JSR_W           = 0xc9;

    /**
    * opcodes:  name by opcode value.
    */
    private static final String[] OPNAME = new String[0x100];
    static
        {
        OPNAME[0x00] = "nop";
        OPNAME[0x01] = "aconst_null";
        OPNAME[0x02] = "iconst_m1";
        OPNAME[0x03] = "iconst_0";
        OPNAME[0x04] = "iconst_1";
        OPNAME[0x05] = "iconst_2";
        OPNAME[0x06] = "iconst_3";
        OPNAME[0x07] = "iconst_4";
        OPNAME[0x08] = "iconst_5";
        OPNAME[0x09] = "lconst_0";
        OPNAME[0x0a] = "lconst_1";
        OPNAME[0x0b] = "fconst_0";
        OPNAME[0x0c] = "fconst_1";
        OPNAME[0x0d] = "fconst_2";
        OPNAME[0x0e] = "dconst_0";
        OPNAME[0x0f] = "dconst_1";
        OPNAME[0x10] = "bipush";
        OPNAME[0x11] = "sipush";
        OPNAME[0x12] = "ldc";
        OPNAME[0x13] = "ldc_w";
        OPNAME[0x14] = "ldc2_w";
        OPNAME[0x15] = "iload";
        OPNAME[0x16] = "lload";
        OPNAME[0x17] = "fload";
        OPNAME[0x18] = "dload";
        OPNAME[0x19] = "aload";
        OPNAME[0x1a] = "iload_0";
        OPNAME[0x1b] = "iload_1";
        OPNAME[0x1c] = "iload_2";
        OPNAME[0x1d] = "iload_3";
        OPNAME[0x1e] = "lload_0";
        OPNAME[0x1f] = "lload_1";
        OPNAME[0x20] = "lload_2";
        OPNAME[0x21] = "lload_3";
        OPNAME[0x22] = "fload_0";
        OPNAME[0x23] = "fload_1";
        OPNAME[0x24] = "fload_2";
        OPNAME[0x25] = "fload_3";
        OPNAME[0x26] = "dload_0";
        OPNAME[0x27] = "dload_1";
        OPNAME[0x28] = "dload_2";
        OPNAME[0x29] = "dload_3";
        OPNAME[0x2a] = "aload_0";
        OPNAME[0x2b] = "aload_1";
        OPNAME[0x2c] = "aload_2";
        OPNAME[0x2d] = "aload_3";
        OPNAME[0x2e] = "iaload";
        OPNAME[0x2f] = "laload";
        OPNAME[0x30] = "faload";
        OPNAME[0x31] = "daload";
        OPNAME[0x32] = "aaload";
        OPNAME[0x33] = "baload";
        OPNAME[0x34] = "caload";
        OPNAME[0x35] = "saload";
        OPNAME[0x36] = "istore";
        OPNAME[0x37] = "lstore";
        OPNAME[0x38] = "fstore";
        OPNAME[0x39] = "dstore";
        OPNAME[0x3a] = "astore";
        OPNAME[0x3b] = "istore_0";
        OPNAME[0x3c] = "istore_1";
        OPNAME[0x3d] = "istore_2";
        OPNAME[0x3e] = "istore_3";
        OPNAME[0x3f] = "lstore_0";
        OPNAME[0x40] = "lstore_1";
        OPNAME[0x41] = "lstore_2";
        OPNAME[0x42] = "lstore_3";
        OPNAME[0x43] = "fstore_0";
        OPNAME[0x44] = "fstore_1";
        OPNAME[0x45] = "fstore_2";
        OPNAME[0x46] = "fstore_3";
        OPNAME[0x47] = "dstore_0";
        OPNAME[0x48] = "dstore_1";
        OPNAME[0x49] = "dstore_2";
        OPNAME[0x4a] = "dstore_3";
        OPNAME[0x4b] = "astore_0";
        OPNAME[0x4c] = "astore_1";
        OPNAME[0x4d] = "astore_2";
        OPNAME[0x4e] = "astore_3";
        OPNAME[0x4f] = "iastore";
        OPNAME[0x50] = "lastore";
        OPNAME[0x51] = "fastore";
        OPNAME[0x52] = "dastore";
        OPNAME[0x53] = "aastore";
        OPNAME[0x54] = "bastore";
        OPNAME[0x55] = "castore";
        OPNAME[0x56] = "sastore";
        OPNAME[0x57] = "pop";
        OPNAME[0x58] = "pop2";
        OPNAME[0x59] = "dup";
        OPNAME[0x5a] = "dup_x1";
        OPNAME[0x5b] = "dup_x2";
        OPNAME[0x5c] = "dup2";
        OPNAME[0x5d] = "dup2_x1";
        OPNAME[0x5e] = "dup2_x2";
        OPNAME[0x5f] = "swap";
        OPNAME[0x60] = "iadd";
        OPNAME[0x61] = "ladd";
        OPNAME[0x62] = "fadd";
        OPNAME[0x63] = "dadd";
        OPNAME[0x64] = "isub";
        OPNAME[0x65] = "lsub";
        OPNAME[0x66] = "fsub";
        OPNAME[0x67] = "dsub";
        OPNAME[0x68] = "imul";
        OPNAME[0x69] = "lmul";
        OPNAME[0x6a] = "fmul";
        OPNAME[0x6b] = "dmul";
        OPNAME[0x6c] = "idiv";
        OPNAME[0x6d] = "ldiv";
        OPNAME[0x6e] = "fdiv";
        OPNAME[0x6f] = "ddiv";
        OPNAME[0x70] = "irem";
        OPNAME[0x71] = "lrem";
        OPNAME[0x72] = "frem";
        OPNAME[0x73] = "drem";
        OPNAME[0x74] = "ineg";
        OPNAME[0x75] = "lneg";
        OPNAME[0x76] = "fneg";
        OPNAME[0x77] = "dneg";
        OPNAME[0x78] = "ishl";
        OPNAME[0x79] = "lshl";
        OPNAME[0x7a] = "ishr";
        OPNAME[0x7b] = "lshr";
        OPNAME[0x7c] = "iushr";
        OPNAME[0x7d] = "lushr";
        OPNAME[0x7e] = "iand";
        OPNAME[0x7f] = "land";
        OPNAME[0x80] = "ior";
        OPNAME[0x81] = "lor";
        OPNAME[0x82] = "ixor";
        OPNAME[0x83] = "lxor";
        OPNAME[0x84] = "iinc";
        OPNAME[0x85] = "i2l";
        OPNAME[0x86] = "i2f";
        OPNAME[0x87] = "i2d";
        OPNAME[0x88] = "l2i";
        OPNAME[0x89] = "l2f";
        OPNAME[0x8a] = "l2d";
        OPNAME[0x8b] = "f2i";
        OPNAME[0x8c] = "f2l";
        OPNAME[0x8d] = "f2d";
        OPNAME[0x8e] = "d2i";
        OPNAME[0x8f] = "d2l";
        OPNAME[0x90] = "d2f";
        OPNAME[0x91] = "i2b";
        OPNAME[0x92] = "i2c";
        OPNAME[0x93] = "i2s";
        OPNAME[0x94] = "lcmp";
        OPNAME[0x95] = "fcmpl";
        OPNAME[0x96] = "fcmpg";
        OPNAME[0x97] = "dcmpl";
        OPNAME[0x98] = "dcmpg";
        OPNAME[0x99] = "ifeq";
        OPNAME[0x9a] = "ifne";
        OPNAME[0x9b] = "iflt";
        OPNAME[0x9c] = "ifge";
        OPNAME[0x9d] = "ifgt";
        OPNAME[0x9e] = "ifle";
        OPNAME[0x9f] = "if_icmpeq";
        OPNAME[0xa0] = "if_icmpne";
        OPNAME[0xa1] = "if_icmplt";
        OPNAME[0xa2] = "if_icmpge";
        OPNAME[0xa3] = "if_icmpgt";
        OPNAME[0xa4] = "if_icmple";
        OPNAME[0xa5] = "if_acmpeq";
        OPNAME[0xa6] = "if_acmpne";
        OPNAME[0xa7] = "goto";
        OPNAME[0xa8] = "jsr";
        OPNAME[0xa9] = "ret";
        OPNAME[0xaa] = "tableswitch";
        OPNAME[0xab] = "lookupswitch";
        OPNAME[0xac] = "ireturn";
        OPNAME[0xad] = "lreturn";
        OPNAME[0xae] = "freturn";
        OPNAME[0xaf] = "dreturn";
        OPNAME[0xb0] = "areturn";
        OPNAME[0xb1] = "return";
        OPNAME[0xb2] = "getstatic";
        OPNAME[0xb3] = "putstatic";
        OPNAME[0xb4] = "getfield";
        OPNAME[0xb5] = "putfield";
        OPNAME[0xb6] = "invokevirtual";
        OPNAME[0xb7] = "invokespecial";
        OPNAME[0xb8] = "invokestatic";
        OPNAME[0xb9] = "invokeinterface";
        OPNAME[0xbb] = "new";
        OPNAME[0xbc] = "newarray";
        OPNAME[0xbd] = "anewarray";
        OPNAME[0xbe] = "arraylength";
        OPNAME[0xbf] = "athrow";
        OPNAME[0xc0] = "checkcast";
        OPNAME[0xc1] = "instanceof";
        OPNAME[0xc2] = "monitorenter";
        OPNAME[0xc3] = "monitorexit";
        OPNAME[0xc4] = "wide";
        OPNAME[0xc5] = "multianewarray";
        OPNAME[0xc6] = "ifnull";
        OPNAME[0xc7] = "ifnonnull";
        OPNAME[0xc8] = "goto_w";
        OPNAME[0xc9] = "jsr_w";
        }

    }


class MarkedByteArrayInputStream extends ByteArrayInputStream
    {
    protected int posPrev;
    protected int posStart;

    public MarkedByteArrayInputStream(byte buf[])
        {
        this(buf, 0, buf.length);
        }

    public MarkedByteArrayInputStream(byte buf[], int offset, int length)
        {
        super(buf, offset, length);
        posPrev  = pos;
        posStart = offset;
        }

    public int getMarkedOffset()
        {
        return posPrev - posStart;
        }

    public int getCurrentOffset()
        {
        return pos - posStart;
        }

    public byte[] getMarkedBytes()
        {
        int     cb = pos - posPrev;
        byte[]  ab = new byte[cb];
        System.arraycopy(buf, posPrev, ab, 0, cb);
        posPrev = pos;
        return ab;
        }
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy