diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/struct/StructMethod.java')
-rw-r--r-- | src/org/jetbrains/java/decompiler/struct/StructMethod.java | 1068 |
1 files changed, 536 insertions, 532 deletions
diff --git a/src/org/jetbrains/java/decompiler/struct/StructMethod.java b/src/org/jetbrains/java/decompiler/struct/StructMethod.java index 20fdae9..baaf633 100644 --- a/src/org/jetbrains/java/decompiler/struct/StructMethod.java +++ b/src/org/jetbrains/java/decompiler/struct/StructMethod.java @@ -1,19 +1,27 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.struct; +import org.jetbrains.java.decompiler.code.*; +import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; +import org.jetbrains.java.decompiler.struct.consts.ConstantPool; +import org.jetbrains.java.decompiler.util.DataInputFullStream; +import org.jetbrains.java.decompiler.util.VBStyleCollection; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -21,19 +29,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.jetbrains.java.decompiler.code.CodeConstants; -import org.jetbrains.java.decompiler.code.ConstantsUtil; -import org.jetbrains.java.decompiler.code.ExceptionHandler; -import org.jetbrains.java.decompiler.code.ExceptionTable; -import org.jetbrains.java.decompiler.code.FullInstructionSequence; -import org.jetbrains.java.decompiler.code.Instruction; -import org.jetbrains.java.decompiler.code.InstructionSequence; -import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; -import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; -import org.jetbrains.java.decompiler.struct.consts.ConstantPool; -import org.jetbrains.java.decompiler.util.DataInputFullStream; -import org.jetbrains.java.decompiler.util.VBStyleCollection; - /* method_info { u2 access_flags; @@ -45,516 +40,525 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; */ public class StructMethod implements CodeConstants { - - // ***************************************************************************** - // public fields - // ***************************************************************************** - - public int name_index; - - public int descriptor_index; - - // ***************************************************************************** - // private fields - // ***************************************************************************** - - private static final int[] opr_iconst = new int[] {-1,0,1,2,3,4,5}; - - private static final int[] opr_loadstore = new int[] {0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3}; - - private static final int[] opcs_load = new int[] {opc_iload,opc_lload,opc_fload,opc_dload,opc_aload}; - - private static final int[] opcs_store = new int[] {opc_istore,opc_lstore,opc_fstore,opc_dstore,opc_astore}; - - - private int accessFlags; - - private VBStyleCollection<StructGeneralAttribute, String> attributes; - - private int localVariables; - - private int maxStack; - - private String name; - - private String descriptor; - - private InstructionSequence seq; - - private boolean containsCode = false; - - private boolean own; - - private StructClass classStruct; - - - // lazy properties - private boolean lazy; - - private boolean expanded; - - private byte[] code_content; - - private int code_length = 0; - - private int code_fulllength = 0; - - // ***************************************************************************** - // constructors - // ***************************************************************************** - - public StructMethod(DataInputFullStream in, boolean own, StructClass clstruct) throws IOException { - this(in, true, own, clstruct); - } - - public StructMethod(DataInputFullStream in, boolean lazy, boolean own, StructClass clstruct) throws IOException { - - this.own = own; - this.lazy = lazy; - this.expanded = !lazy; - this.classStruct = clstruct; - - accessFlags = in.readUnsignedShort(); - name_index = in.readUnsignedShort(); - descriptor_index = in.readUnsignedShort(); - - ConstantPool pool = clstruct.getPool(); - - initStrings(pool, clstruct.this_class); - - VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); - int len = in.readUnsignedShort(); - for(int i=0;i<len;i++) { - - int attr_nameindex = in.readUnsignedShort(); - String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); - - if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { - if(!this.own) { - // skip code in foreign classes - in.skip(8); - in.skip(in.readInt()); - in.skip(8*in.readUnsignedShort()); - } else { - containsCode = true; - - in.skip(4); - - maxStack = in.readUnsignedShort(); - localVariables = in.readUnsignedShort(); - - if(lazy) { - code_length = in.readInt(); - - in.skip(code_length); - - int exc_length = in.readUnsignedShort(); - code_fulllength = code_length + exc_length*8+2; - - in.skip(exc_length*8); - - } else { - seq = parseBytecode(in, in.readInt(), pool); - } - } - - // code attributes - int length = in.readUnsignedShort(); - for (int j = 0; j < length; j++) { - int codeattr_nameindex = in.readUnsignedShort(); - String codeattrname = pool.getPrimitiveConstant(codeattr_nameindex).getString(); - - readAttribute(in, pool, lstAttribute, codeattr_nameindex, codeattrname); - } - } else { - readAttribute(in, pool, lstAttribute, attr_nameindex, attrname); - } - } - - attributes = lstAttribute; - } - - - - // ***************************************************************************** - // public methods - // ***************************************************************************** - - public void writeToStream(DataOutputStream out) throws IOException { - - out.writeShort(accessFlags); - out.writeShort(name_index); - out.writeShort(descriptor_index); - - out.writeShort(attributes.size()); - - for(StructGeneralAttribute attr: attributes) { - if(StructGeneralAttribute.ATTRIBUTE_CODE.equals(attr.getName())){ - out.writeShort(attr.getAttribute_name_index()); - - if(lazy && !expanded) { - out.writeInt(10+code_content.length); - out.writeShort(maxStack); - out.writeShort(localVariables); - out.writeInt(code_length); - out.write(code_content); - } else { - ByteArrayOutputStream codeout = new ByteArrayOutputStream(); - seq.writeCodeToStream(new DataOutputStream(codeout)); - - ByteArrayOutputStream excout = new ByteArrayOutputStream(); - seq.writeExceptionsToStream(new DataOutputStream(excout)); - - out.writeInt(10+codeout.size()+excout.size()); - - out.writeShort(maxStack); - out.writeShort(localVariables); - out.writeInt(codeout.size()); - codeout.writeTo(out); - excout.writeTo(out); - } - // no attributes - out.writeShort(0); - } else { - attr.writeToStream(out); - } - } - - } - - private void readAttribute(DataInputFullStream in, ConstantPool pool, VBStyleCollection<StructGeneralAttribute, String> lstAttribute, - int attr_nameindex, String attrname) throws IOException { - - StructGeneralAttribute attribute = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); - - if(attribute != null) { - attrname = attribute.getName(); - - byte[] arr = new byte[in.readInt()]; - in.readFull(arr); - attribute.setInfo(arr); - - attribute.initContent(pool); - - if(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname) && - lstAttribute.containsKey(attrname)) { - // merge all variable tables - StructLocalVariableTableAttribute oldattr = (StructLocalVariableTableAttribute)lstAttribute.getWithKey(attrname); - oldattr.addLocalVariableTable((StructLocalVariableTableAttribute)attribute); - } else { - lstAttribute.addWithKey(attribute, attribute.getName()); - } - } else { - in.skip(in.readInt()); - } - } - - private void initStrings(ConstantPool pool, int class_index) { - String[] values = pool.getClassElement(ConstantPool.METHOD, class_index, name_index, descriptor_index); - name = values[0]; - descriptor = values[1]; - } - - public void expandData() throws IOException { - if(containsCode && lazy && !expanded) { - - byte[] codearr = classStruct.getLoader().loadBytecode(this, code_fulllength); - - seq = parseBytecode(new DataInputFullStream(new ByteArrayInputStream(codearr)), code_length, classStruct.getPool()); - expanded = true; - } - } - - public void releaseResources() throws IOException { - if(containsCode && lazy && expanded) { - seq = null; - expanded = false; - } - } - - // ***************************************************************************** - // private methods - // ***************************************************************************** - - private InstructionSequence parseBytecode(DataInputFullStream in, int length, ConstantPool pool) throws IOException { - - VBStyleCollection<Instruction, Integer> collinstr = new VBStyleCollection<Instruction, Integer>(); - - int bytecode_version = classStruct.getBytecodeVersion(); - - for(int i=0;i<length;) { - - int offset = i; - - int opcode = in.readUnsignedByte(); - int group = GROUP_GENERAL; - - boolean wide = (opcode == opc_wide); - - if(wide) { - i++; - opcode = in.readUnsignedByte(); - } - - List<Integer> operands = new ArrayList<Integer>(); - - if(opcode>=opc_iconst_m1 && opcode<=opc_iconst_5) { - operands.add(new Integer(opr_iconst[opcode-opc_iconst_m1])); - opcode = opc_bipush; - }else if(opcode>=opc_iload_0 && opcode<=opc_aload_3) { - operands.add(new Integer(opr_loadstore[opcode-opc_iload_0])); - opcode = opcs_load[(opcode-opc_iload_0)/4]; - }else if(opcode>=opc_istore_0 && opcode<=opc_astore_3) { - operands.add(new Integer(opr_loadstore[opcode-opc_istore_0])); - opcode = opcs_store[(opcode-opc_istore_0)/4]; - } else { - switch (opcode) { - case opc_bipush: - operands.add(new Integer(in.readByte())); - i++; - break; - case opc_ldc: - case opc_newarray: - operands.add(new Integer(in.readUnsignedByte())); - i++; - break; - case opc_sipush: - case opc_ifeq: - case opc_ifne: - case opc_iflt: - case opc_ifge: - case opc_ifgt: - case opc_ifle: - case opc_if_icmpeq: - case opc_if_icmpne: - case opc_if_icmplt: - case opc_if_icmpge: - case opc_if_icmpgt: - case opc_if_icmple: - case opc_if_acmpeq: - case opc_if_acmpne: - case opc_goto: - case opc_jsr: - case opc_ifnull: - case opc_ifnonnull: - if(opcode!=opc_sipush) { - group = GROUP_JUMP; - } - operands.add(new Integer(in.readShort())); - i+=2; - break; - case opc_ldc_w: - case opc_ldc2_w: - case opc_getstatic: - case opc_putstatic: - case opc_getfield: - case opc_putfield: - case opc_invokevirtual: - case opc_invokespecial: - case opc_invokestatic: - case opc_new: - case opc_anewarray: - case opc_checkcast: - case opc_instanceof: - operands.add(new Integer(in.readUnsignedShort())); - i+=2; - if(opcode>=opc_getstatic && opcode<=opc_putfield) { - group = GROUP_FIELDACCESS; - } else if(opcode>=opc_invokevirtual && opcode<=opc_invokestatic) { - group = GROUP_INVOCATION; - } - break; - case opc_invokedynamic: - if(classStruct.isVersionGE_1_7()) { // instruction unused in Java 6 and before - operands.add(new Integer(in.readUnsignedShort())); - in.skip(2); - group = GROUP_INVOCATION; - i+=4; - } - break; - case opc_iload: - case opc_lload: - case opc_fload: - case opc_dload: - case opc_aload: - case opc_istore: - case opc_lstore: - case opc_fstore: - case opc_dstore: - case opc_astore: - case opc_ret: - if(wide) { - operands.add(new Integer(in.readUnsignedShort())); - i+=2; - } else { - operands.add(new Integer(in.readUnsignedByte())); - i++; - } - if(opcode == opc_ret) { - group = GROUP_RETURN; - } - break; - case opc_iinc: - if (wide) { - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readShort())); - i+=4; - } else { - operands.add(new Integer(in.readUnsignedByte())); - operands.add(new Integer(in.readByte())); - i+=2; - } - break; - case opc_goto_w: - case opc_jsr_w: - opcode = opcode == opc_jsr_w?opc_jsr:opc_goto; - operands.add(new Integer(in.readInt())); - group = GROUP_JUMP; - i+=4; - break; - case opc_invokeinterface: - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readUnsignedByte())); - in.skip(1); - group = GROUP_INVOCATION; - i+=4; - break; - case opc_multianewarray: - operands.add(new Integer(in.readUnsignedShort())); - operands.add(new Integer(in.readUnsignedByte())); - i+=3; - break; - case opc_tableswitch: - in.skip((4-(i+1)%4)%4); - i+=((4-(i+1)%4)%4); // padding - operands.add(new Integer(in.readInt())); - i+=4; - int low = in.readInt(); - operands.add(new Integer(low)); - i+=4; - int high = in.readInt(); - operands.add(new Integer(high)); - i+=4; - - for(int j=0;j<high-low+1;j++) { - operands.add(new Integer(in.readInt())); - i+=4; - } - group = GROUP_SWITCH; - - break; - case opc_lookupswitch: - in.skip((4-(i+1)%4)%4); - i+=((4-(i+1)%4)%4); // padding - operands.add(new Integer(in.readInt())); - i+=4; - int npairs = in.readInt(); - operands.add(new Integer(npairs)); - i+=4; - - for(int j=0;j<npairs;j++) { - operands.add(new Integer(in.readInt())); - i+=4; - operands.add(new Integer(in.readInt())); - i+=4; - } - group = GROUP_SWITCH; - break; - case opc_ireturn: - case opc_lreturn: - case opc_freturn: - case opc_dreturn: - case opc_areturn: - case opc_return: - case opc_athrow: - group = GROUP_RETURN; - } - } - - int[] ops = new int[operands.size()]; - for(int j=0;j<operands.size();j++) { - ops[j] = ((Integer)operands.get(j)).intValue(); - } - - Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, ops); - - collinstr.addWithKey(instr, new Integer(offset)); - - i++; - } - - // initialize exception table - List<ExceptionHandler> lstHandlers = new ArrayList<ExceptionHandler>(); - - int exception_count = in.readUnsignedShort(); - for(int i=0;i<exception_count;i++) { - ExceptionHandler handler = new ExceptionHandler(); - handler.from = in.readUnsignedShort(); - handler.to = in.readUnsignedShort(); - handler.handler = in.readUnsignedShort(); - - int excclass = in.readUnsignedShort(); - handler.class_index = excclass; - if(excclass!=0) { - handler.exceptionClass = pool.getPrimitiveConstant(excclass).getString(); - } - - lstHandlers.add(handler); - } - - InstructionSequence seq = new FullInstructionSequence(collinstr, new ExceptionTable(lstHandlers)); - - // initialize instructions - int i = seq.length()-1; - seq.setPointer(i); - - while(i>=0) { - Instruction instr = seq.getInstr(i--); - if(instr.group!=GROUP_GENERAL) { - instr.initInstruction(seq); - } - seq.addToPointer(-1); - } - - return seq; - - } - - // ***************************************************************************** - // getter and setter methods - // ***************************************************************************** - - public InstructionSequence getInstructionSequence() { - return seq; - } - - public String getDescriptor() { - return descriptor; - } - - public String getName() { - return name; - } - - public int getAccessFlags() { - return accessFlags; - } - - public int getLocalVariables() { - return localVariables; - } - - public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { - return attributes; - } - - public StructClass getClassStruct() { - return classStruct; - } - - public boolean containsCode() { - return containsCode; - } + + // ***************************************************************************** + // public fields + // ***************************************************************************** + + public int name_index; + + public int descriptor_index; + + // ***************************************************************************** + // private fields + // ***************************************************************************** + + private static final int[] opr_iconst = new int[]{-1, 0, 1, 2, 3, 4, 5}; + + private static final int[] opr_loadstore = new int[]{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}; + + private static final int[] opcs_load = new int[]{opc_iload, opc_lload, opc_fload, opc_dload, opc_aload}; + + private static final int[] opcs_store = new int[]{opc_istore, opc_lstore, opc_fstore, opc_dstore, opc_astore}; + + + private int accessFlags; + + private VBStyleCollection<StructGeneralAttribute, String> attributes; + + private int localVariables; + + private int maxStack; + + private String name; + + private String descriptor; + + private InstructionSequence seq; + + private boolean containsCode = false; + + private boolean own; + + private StructClass classStruct; + + + // lazy properties + private boolean lazy; + + private boolean expanded; + + private byte[] code_content; + + private int code_length = 0; + + private int code_fulllength = 0; + + // ***************************************************************************** + // constructors + // ***************************************************************************** + + public StructMethod(DataInputFullStream in, boolean own, StructClass clstruct) throws IOException { + this(in, true, own, clstruct); + } + + public StructMethod(DataInputFullStream in, boolean lazy, boolean own, StructClass clstruct) throws IOException { + + this.own = own; + this.lazy = lazy; + this.expanded = !lazy; + this.classStruct = clstruct; + + accessFlags = in.readUnsignedShort(); + name_index = in.readUnsignedShort(); + descriptor_index = in.readUnsignedShort(); + + ConstantPool pool = clstruct.getPool(); + + initStrings(pool, clstruct.this_class); + + VBStyleCollection<StructGeneralAttribute, String> lstAttribute = new VBStyleCollection<StructGeneralAttribute, String>(); + int len = in.readUnsignedShort(); + for (int i = 0; i < len; i++) { + + int attr_nameindex = in.readUnsignedShort(); + String attrname = pool.getPrimitiveConstant(attr_nameindex).getString(); + + if (StructGeneralAttribute.ATTRIBUTE_CODE.equals(attrname)) { + if (!this.own) { + // skip code in foreign classes + in.skip(8); + in.skip(in.readInt()); + in.skip(8 * in.readUnsignedShort()); + } + else { + containsCode = true; + + in.skip(4); + + maxStack = in.readUnsignedShort(); + localVariables = in.readUnsignedShort(); + + if (lazy) { + code_length = in.readInt(); + + in.skip(code_length); + + int exc_length = in.readUnsignedShort(); + code_fulllength = code_length + exc_length * 8 + 2; + + in.skip(exc_length * 8); + } + else { + seq = parseBytecode(in, in.readInt(), pool); + } + } + + // code attributes + int length = in.readUnsignedShort(); + for (int j = 0; j < length; j++) { + int codeattr_nameindex = in.readUnsignedShort(); + String codeattrname = pool.getPrimitiveConstant(codeattr_nameindex).getString(); + + readAttribute(in, pool, lstAttribute, codeattr_nameindex, codeattrname); + } + } + else { + readAttribute(in, pool, lstAttribute, attr_nameindex, attrname); + } + } + + attributes = lstAttribute; + } + + + // ***************************************************************************** + // public methods + // ***************************************************************************** + + public void writeToStream(DataOutputStream out) throws IOException { + + out.writeShort(accessFlags); + out.writeShort(name_index); + out.writeShort(descriptor_index); + + out.writeShort(attributes.size()); + + for (StructGeneralAttribute attr : attributes) { + if (StructGeneralAttribute.ATTRIBUTE_CODE.equals(attr.getName())) { + out.writeShort(attr.getAttribute_name_index()); + + if (lazy && !expanded) { + out.writeInt(10 + code_content.length); + out.writeShort(maxStack); + out.writeShort(localVariables); + out.writeInt(code_length); + out.write(code_content); + } + else { + ByteArrayOutputStream codeout = new ByteArrayOutputStream(); + seq.writeCodeToStream(new DataOutputStream(codeout)); + + ByteArrayOutputStream excout = new ByteArrayOutputStream(); + seq.writeExceptionsToStream(new DataOutputStream(excout)); + + out.writeInt(10 + codeout.size() + excout.size()); + + out.writeShort(maxStack); + out.writeShort(localVariables); + out.writeInt(codeout.size()); + codeout.writeTo(out); + excout.writeTo(out); + } + // no attributes + out.writeShort(0); + } + else { + attr.writeToStream(out); + } + } + } + + private void readAttribute(DataInputFullStream in, ConstantPool pool, VBStyleCollection<StructGeneralAttribute, String> lstAttribute, + int attr_nameindex, String attrname) throws IOException { + + StructGeneralAttribute attribute = StructGeneralAttribute.getMatchingAttributeInstance(attr_nameindex, attrname); + + if (attribute != null) { + attrname = attribute.getName(); + + byte[] arr = new byte[in.readInt()]; + in.readFull(arr); + attribute.setInfo(arr); + + attribute.initContent(pool); + + if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname) && + lstAttribute.containsKey(attrname)) { + // merge all variable tables + StructLocalVariableTableAttribute oldattr = (StructLocalVariableTableAttribute)lstAttribute.getWithKey(attrname); + oldattr.addLocalVariableTable((StructLocalVariableTableAttribute)attribute); + } + else { + lstAttribute.addWithKey(attribute, attribute.getName()); + } + } + else { + in.skip(in.readInt()); + } + } + + private void initStrings(ConstantPool pool, int class_index) { + String[] values = pool.getClassElement(ConstantPool.METHOD, class_index, name_index, descriptor_index); + name = values[0]; + descriptor = values[1]; + } + + public void expandData() throws IOException { + if (containsCode && lazy && !expanded) { + + byte[] codearr = classStruct.getLoader().loadBytecode(this, code_fulllength); + + seq = parseBytecode(new DataInputFullStream(new ByteArrayInputStream(codearr)), code_length, classStruct.getPool()); + expanded = true; + } + } + + public void releaseResources() throws IOException { + if (containsCode && lazy && expanded) { + seq = null; + expanded = false; + } + } + + // ***************************************************************************** + // private methods + // ***************************************************************************** + + private InstructionSequence parseBytecode(DataInputFullStream in, int length, ConstantPool pool) throws IOException { + + VBStyleCollection<Instruction, Integer> collinstr = new VBStyleCollection<Instruction, Integer>(); + + int bytecode_version = classStruct.getBytecodeVersion(); + + for (int i = 0; i < length; ) { + + int offset = i; + + int opcode = in.readUnsignedByte(); + int group = GROUP_GENERAL; + + boolean wide = (opcode == opc_wide); + + if (wide) { + i++; + opcode = in.readUnsignedByte(); + } + + List<Integer> operands = new ArrayList<Integer>(); + + if (opcode >= opc_iconst_m1 && opcode <= opc_iconst_5) { + operands.add(new Integer(opr_iconst[opcode - opc_iconst_m1])); + opcode = opc_bipush; + } + else if (opcode >= opc_iload_0 && opcode <= opc_aload_3) { + operands.add(new Integer(opr_loadstore[opcode - opc_iload_0])); + opcode = opcs_load[(opcode - opc_iload_0) / 4]; + } + else if (opcode >= opc_istore_0 && opcode <= opc_astore_3) { + operands.add(new Integer(opr_loadstore[opcode - opc_istore_0])); + opcode = opcs_store[(opcode - opc_istore_0) / 4]; + } + else { + switch (opcode) { + case opc_bipush: + operands.add(new Integer(in.readByte())); + i++; + break; + case opc_ldc: + case opc_newarray: + operands.add(new Integer(in.readUnsignedByte())); + i++; + break; + case opc_sipush: + case opc_ifeq: + case opc_ifne: + case opc_iflt: + case opc_ifge: + case opc_ifgt: + case opc_ifle: + case opc_if_icmpeq: + case opc_if_icmpne: + case opc_if_icmplt: + case opc_if_icmpge: + case opc_if_icmpgt: + case opc_if_icmple: + case opc_if_acmpeq: + case opc_if_acmpne: + case opc_goto: + case opc_jsr: + case opc_ifnull: + case opc_ifnonnull: + if (opcode != opc_sipush) { + group = GROUP_JUMP; + } + operands.add(new Integer(in.readShort())); + i += 2; + break; + case opc_ldc_w: + case opc_ldc2_w: + case opc_getstatic: + case opc_putstatic: + case opc_getfield: + case opc_putfield: + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic: + case opc_new: + case opc_anewarray: + case opc_checkcast: + case opc_instanceof: + operands.add(new Integer(in.readUnsignedShort())); + i += 2; + if (opcode >= opc_getstatic && opcode <= opc_putfield) { + group = GROUP_FIELDACCESS; + } + else if (opcode >= opc_invokevirtual && opcode <= opc_invokestatic) { + group = GROUP_INVOCATION; + } + break; + case opc_invokedynamic: + if (classStruct.isVersionGE_1_7()) { // instruction unused in Java 6 and before + operands.add(new Integer(in.readUnsignedShort())); + in.skip(2); + group = GROUP_INVOCATION; + i += 4; + } + break; + case opc_iload: + case opc_lload: + case opc_fload: + case opc_dload: + case opc_aload: + case opc_istore: + case opc_lstore: + case opc_fstore: + case opc_dstore: + case opc_astore: + case opc_ret: + if (wide) { + operands.add(new Integer(in.readUnsignedShort())); + i += 2; + } + else { + operands.add(new Integer(in.readUnsignedByte())); + i++; + } + if (opcode == opc_ret) { + group = GROUP_RETURN; + } + break; + case opc_iinc: + if (wide) { + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readShort())); + i += 4; + } + else { + operands.add(new Integer(in.readUnsignedByte())); + operands.add(new Integer(in.readByte())); + i += 2; + } + break; + case opc_goto_w: + case opc_jsr_w: + opcode = opcode == opc_jsr_w ? opc_jsr : opc_goto; + operands.add(new Integer(in.readInt())); + group = GROUP_JUMP; + i += 4; + break; + case opc_invokeinterface: + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readUnsignedByte())); + in.skip(1); + group = GROUP_INVOCATION; + i += 4; + break; + case opc_multianewarray: + operands.add(new Integer(in.readUnsignedShort())); + operands.add(new Integer(in.readUnsignedByte())); + i += 3; + break; + case opc_tableswitch: + in.skip((4 - (i + 1) % 4) % 4); + i += ((4 - (i + 1) % 4) % 4); // padding + operands.add(new Integer(in.readInt())); + i += 4; + int low = in.readInt(); + operands.add(new Integer(low)); + i += 4; + int high = in.readInt(); + operands.add(new Integer(high)); + i += 4; + + for (int j = 0; j < high - low + 1; j++) { + operands.add(new Integer(in.readInt())); + i += 4; + } + group = GROUP_SWITCH; + + break; + case opc_lookupswitch: + in.skip((4 - (i + 1) % 4) % 4); + i += ((4 - (i + 1) % 4) % 4); // padding + operands.add(new Integer(in.readInt())); + i += 4; + int npairs = in.readInt(); + operands.add(new Integer(npairs)); + i += 4; + + for (int j = 0; j < npairs; j++) { + operands.add(new Integer(in.readInt())); + i += 4; + operands.add(new Integer(in.readInt())); + i += 4; + } + group = GROUP_SWITCH; + break; + case opc_ireturn: + case opc_lreturn: + case opc_freturn: + case opc_dreturn: + case opc_areturn: + case opc_return: + case opc_athrow: + group = GROUP_RETURN; + } + } + + int[] ops = new int[operands.size()]; + for (int j = 0; j < operands.size(); j++) { + ops[j] = ((Integer)operands.get(j)).intValue(); + } + + Instruction instr = ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, ops); + + collinstr.addWithKey(instr, new Integer(offset)); + + i++; + } + + // initialize exception table + List<ExceptionHandler> lstHandlers = new ArrayList<ExceptionHandler>(); + + int exception_count = in.readUnsignedShort(); + for (int i = 0; i < exception_count; i++) { + ExceptionHandler handler = new ExceptionHandler(); + handler.from = in.readUnsignedShort(); + handler.to = in.readUnsignedShort(); + handler.handler = in.readUnsignedShort(); + + int excclass = in.readUnsignedShort(); + handler.class_index = excclass; + if (excclass != 0) { + handler.exceptionClass = pool.getPrimitiveConstant(excclass).getString(); + } + + lstHandlers.add(handler); + } + + InstructionSequence seq = new FullInstructionSequence(collinstr, new ExceptionTable(lstHandlers)); + + // initialize instructions + int i = seq.length() - 1; + seq.setPointer(i); + + while (i >= 0) { + Instruction instr = seq.getInstr(i--); + if (instr.group != GROUP_GENERAL) { + instr.initInstruction(seq); + } + seq.addToPointer(-1); + } + + return seq; + } + + // ***************************************************************************** + // getter and setter methods + // ***************************************************************************** + + public InstructionSequence getInstructionSequence() { + return seq; + } + + public String getDescriptor() { + return descriptor; + } + + public String getName() { + return name; + } + + public int getAccessFlags() { + return accessFlags; + } + + public int getLocalVariables() { + return localVariables; + } + + public VBStyleCollection<StructGeneralAttribute, String> getAttributes() { + return attributes; + } + + public StructClass getClassStruct() { + return classStruct; + } + + public boolean containsCode() { + return containsCode; + } } |