/** @return an array of instructions without target information for branch instructions. */ public Instruction[] getInstructions() { ByteSequence bytes = new ByteSequence(getByteCode()); List<Instruction> instructions = new ArrayList<Instruction>(); try { while (bytes.available() > 0) { instructions.add(Instruction.readInstruction(bytes)); } } catch (IOException e) { throw new ClassGenException(e.toString(), e); } return instructions.toArray(new Instruction[instructions.size()]); }
/** * Initialize instruction list from byte array. * * @param code byte array containing the instructions */ public InstructionList(byte[] code) { ByteSequence bytes = new ByteSequence(code); InstructionHandle[] ihs = new InstructionHandle[code.length]; int[] pos = new int[code.length]; // Can't be more than that int count = 0; // Contains actual length /* Pass 1: Create an object for each byte code and append them * to the list. */ try { while (bytes.available() > 0) { // Remember byte offset and associate it with the instruction int off = bytes.getIndex(); pos[count] = off; /* Read one instruction from the byte stream, the byte position is set * accordingly. */ Instruction i = Instruction.readInstruction(bytes); InstructionHandle ih; if (i instanceof BranchInstruction) { ih = append((BranchInstruction) i); } else { ih = append(i); } ih.setPosition(off); ihs[count] = ih; count++; } } catch (IOException e) { throw new ClassGenException(e.toString(), e); } byte_positions = new int[count]; // Trim to proper size System.arraycopy(pos, 0, byte_positions, 0, count); /* Pass 2: Look for BranchInstruction and update their targets, i.e., * convert offsets to instruction handles. */ for (int i = 0; i < count; i++) { if (ihs[i] instanceof BranchHandle) { BranchInstruction bi = (BranchInstruction) ihs[i].instruction; int target = bi.position + bi.getIndex(); /* Byte code position: * relative -> absolute. */ // Search for target position InstructionHandle ih = findHandle(ihs, pos, count, target); if (ih == null) { throw new ClassGenException("Couldn't find target for branch: " + bi); } bi.setTarget(ih); // Update target // If it is a Select instruction, update all branch targets if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH Select s = (Select) bi; int[] indices = s.getIndices(); for (int j = 0; j < indices.length; j++) { target = bi.position + indices[j]; ih = findHandle(ihs, pos, count, target); if (ih == null) { throw new ClassGenException("Couldn't find target for switch: " + bi); } s.setTarget(j, ih); // Update target } } } } }