/** * Read an instruction from (byte code) input stream and return the appropiate object. * * @param file file to read from * @return instruction object being read */ public static final Instruction readInstruction(ByteSequence bytes) throws IOException { boolean wide = false; short opcode = (short) bytes.readUnsignedByte(); Instruction obj = null; if (opcode == Constants.WIDE) { // Read next opcode after wide byte wide = true; opcode = (short) bytes.readUnsignedByte(); } if (InstructionConstants.INSTRUCTIONS[opcode] != null) return InstructionConstants.INSTRUCTIONS[ opcode]; // Used predefined immutable object, if available /* Find appropiate class, instantiate an (empty) instruction object * and initialize it by hand. */ Class clazz; try { clazz = Class.forName(className(opcode)); } catch (ClassNotFoundException cnfe) { // If a class by that name does not exist, the opcode is illegal. // Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense. throw new ClassGenException("Illegal opcode detected."); } try { obj = (Instruction) clazz.newInstance(); if (wide && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) throw new Exception("Illegal opcode after wide: " + opcode); obj.setOpcode(opcode); obj.initFromFile(bytes, wide); // Do further initializations, if any // Byte code offset set in InstructionList } catch (Exception e) { throw new ClassGenException(e.toString()); } return obj; }
/** Dump instruction as short code to stream out. */ public void dump(DataOutputStream out) throws IOException { super.dump(out); out.writeShort(b); }