    View Javadoc
    1   package org.apache.bcel.generic;
    2
    3   /* ====================================================================
    4    * The Apache Software License, Version 1.1
    5    *
    6    * Copyright (c) 2001 The Apache Software Foundation.  All rights
    7    * reserved.
    8    *
    9    * Redistribution and use in source and binary forms, with or without
    10   * modification, are permitted provided that the following conditions
    11   * are met:
    12   *
    13   * 1. Redistributions of source code must retain the above copyright
    14   *    notice, this list of conditions and the following disclaimer.
    15   *
    16   * 2. Redistributions in binary form must reproduce the above copyright
    17   *    notice, this list of conditions and the following disclaimer in
    18   *    the documentation and/or other materials provided with the
    19   *    distribution.
    20   *
    21   * 3. The end-user documentation included with the redistribution,
    22   *    if any, must include the following acknowledgment:
    23   *       "This product includes software developed by the
    24   *        Apache Software Foundation (http://www.apache.org/)."
    25   *    Alternately, this acknowledgment may appear in the software itself,
    26   *    if and wherever such third-party acknowledgments normally appear.
    27   *
    28   * 4. The names "Apache" and "Apache Software Foundation" and
    29   *    "Apache BCEL" must not be used to endorse or promote products
    30   *    derived from this software without prior written permission. For
    31   *    written permission, please contact apache@apache.org.
    32   *
    33   * 5. Products derived from this software may not be called "Apache",
    34   *    "Apache BCEL", nor may "Apache" appear in their name, without
    35   *    prior written permission of the Apache Software Foundation.
    36   *
    37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
    41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    48   * SUCH DAMAGE.
    49   * ====================================================================
    50   *
    51   * This software consists of voluntary contributions made by many
    52   * individuals on behalf of the Apache Software Foundation.  For more
    53   * information on the Apache Software Foundation, please see
    54   * <http://www.apache.org/>;.
    55   */
    56
    57  import org.apache.bcel.Constants;
    58  import org.apache.bcel.classfile.Utility;
    59  import org.apache.bcel.classfile.ConstantPool;
    60  import java.io.*;
    61  import org.apache.bcel.util.ByteSequence;
    62
    63  /***
    64   * Abstract super class for all Java byte codes.
    65   *
    66   * @version $Id: Instruction.java,v 1.3 2002/08/07 18:01:32 mdahm Exp $
    67   * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
    68   */
    69  public abstract class Instruction implements Cloneable, Serializable {
    70    protected short length = 1;  // Length of instruction in bytes
    71    protected short opcode = -1; // Opcode number
    72
    73    private static InstructionComparator cmp = InstructionComparator.DEFAULT;
    74
    75    /***
    76     * Empty constructor needed for the Class.newInstance() statement in
    77     * Instruction.readInstruction(). Not to be used otherwise.
    78     */
    79    Instruction() {}
    80
    81    public Instruction(short opcode, short length) {
    82      this.length = length;
    83      this.opcode = opcode;
    84    }
    85
    86    /***
    87     * Dump instruction as byte code to stream out.
    88     * @param out Output stream
    89     */
    90    public void dump(DataOutputStream out) throws IOException {
    91      out.writeByte(opcode); // Common for all instructions
    92    }
    93
    94    /*** @return name of instruction, i.e., opcode name
    95     */
    96    public String getName() {
    97      return Constants.OPCODE_NAMES[opcode];
    98    }
    99
    100   /***
    101    * Long output format:
    102    *
    103    * <name of opcode> "["<opcode number>"]"
    104    * "("<length of instruction>")"
    105    *
    106    * @param verbose long/short format switch
    107    * @return mnemonic for instruction
    108    */
    109   public String toString(boolean verbose) {
    110     if(verbose)
    111       return getName() + "[" + opcode + "](" + length + ")";
    112     else
    113       return getName();
    114   }
    115
    116   /***
    117    * @return mnemonic for instruction in verbose format
    118    */
    119   public String toString() {
    120     return toString(true);
    121   }
    122
    123   /***
    124    * @return mnemonic for instruction with sumbolic references resolved
    125    */
    126   public String toString(ConstantPool cp) {
    127     return toString(false);
    128   }
    129
    130   /***
    131    * Use with caution, since `BranchInstruction's have a `target' reference which
    132    * is not copied correctly (only basic types are). This also applies for
    133    * `Select' instructions with their multiple branch targets.
    134    *
    135    * @see BranchInstruction
    136    * @return (shallow) copy of an instruction
    137    */
    138   public Instruction copy() {
    139     Instruction i = null;
    140
    141     // "Constant" instruction, no need to duplicate
    142     if(InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null)
    143       i = this;
    144     else {
    145       try {
    146 	i = (Instruction)clone();
    147       } catch(CloneNotSupportedException e) {
    148 	System.err.println(e);
    149       }
    150     }
    151
    152     return i;
    153   }
    154
    155   /***
    156    * Read needed data (e.g. index) from file.
    157    *
    158    * @param bytes byte sequence to read from
    159    * @param wide "wide" instruction flag
    160    */
    161   protected void initFromFile(ByteSequence bytes, boolean wide)
    162     throws IOException
    163   {}
    164
    165   /***
    166    * Read an instruction from (byte code) input stream and return the
    167    * appropiate object.
    168    *
    169    * @param file file to read from
    170    * @return instruction object being read
    171    */
    172   public static final Instruction readInstruction(ByteSequence bytes)
    173     throws IOException
    174   {
    175     boolean     wide   = false;
    176     short       opcode = (short)bytes.readUnsignedByte();
    177     Instruction obj    = null;
    178
    179     if(opcode == Constants.WIDE) { // Read next opcode after wide byte
    180       wide = true;
    181       opcode  = (short)bytes.readUnsignedByte();
    182     }
    183
    184     if(InstructionConstants.INSTRUCTIONS[opcode] != null)
    185       return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available
    186
    187     /* Find appropiate class, instantiate an (empty) instruction object
    188      * and initialize it by hand.
    189      */
    190     Class clazz;
    191
    192     try {
    193       clazz = Class.forName(className(opcode));
    194     } catch (ClassNotFoundException cnfe){
    195       // If a class by that name does not exist, the opcode is illegal.
    196       // Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense.
    197       throw new ClassGenException("Illegal opcode detected.");
    198     }
    199
    200     try {
    201       obj = (Instruction)clazz.newInstance();
    202
    203       if(wide && !((obj instanceof LocalVariableInstruction) ||
    204 		   (obj instanceof IINC) ||
    205 		   (obj instanceof RET)))
    206 	throw new Exception("Illegal opcode after wide: " + opcode);
    207
    208       obj.setOpcode(opcode);
    209       obj.initFromFile(bytes, wide); // Do further initializations, if any
    210       // Byte code offset set in InstructionList
    211     } catch(Exception e) { throw new ClassGenException(e.toString()); }
    212
    213     return obj;
    214   }
    215
    216   private static final String className(short opcode) {
    217     String name = Constants.OPCODE_NAMES[opcode].toUpperCase();
    218
    219     /* ICONST_0, etc. will be shortened to ICONST, etc., since ICONST_0 and the like
    220      * are not implemented (directly).
    221      */
    222     try {
    223       int  len = name.length();
    224       char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
    225
    226       if((ch1 == '_') && (ch2 >= '0')  && (ch2 <= '5'))
    227 	name = name.substring(0, len - 2);
    228
    229       if(name.equals("ICONST_M1")) // Special case
    230 	name = "ICONST";
    231     } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
    232
    233     return "org.apache.bcel.generic." + name;
    234   }
    235
    236   /***
    237    * This method also gives right results for instructions whose
    238    * effect on the stack depends on the constant pool entry they
    239    * reference.
    240    *  @return Number of words consumed from stack by this instruction,
    241    * or Constants.UNPREDICTABLE, if this can not be computed statically
    242    */
    243   public int consumeStack(ConstantPoolGen cpg) {
    244     return Constants.CONSUME_STACK[opcode];
    245   }
    246
    247   /***
    248    * This method also gives right results for instructions whose
    249    * effect on the stack depends on the constant pool entry they
    250    * reference.
    251    * @return Number of words produced onto stack by this instruction,
    252    * or Constants.UNPREDICTABLE, if this can not be computed statically
    253    */
    254   public int produceStack(ConstantPoolGen cpg) {
    255     return Constants.PRODUCE_STACK[opcode];
    256   }
    257
    258   /***
    259    * @return this instructions opcode
    260    */
    261   public short getOpcode()    { return opcode; }
    262
    263   /***
    264    * @return length (in bytes) of instruction
    265    */
    266   public int getLength()   { return length; }
    267
    268   /***
    269    * Needed in readInstruction.
    270    */
    271   private void setOpcode(short opcode) { this.opcode = opcode; }
    272
    273   /*** Some instructions may be reused, so don't do anything by default.
    274    */
    275   void dispose() {}
    276
    277   /***
    278    * Call corresponding visitor method(s). The order is:
    279    * Call visitor methods of implemented interfaces first, then
    280    * call methods according to the class hierarchy in descending order,
    281    * i.e., the most specific visitXXX() call comes last.
    282    *
    283    * @param v Visitor object
    284    */
    285   public abstract void accept(Visitor v);
    286
    287   /*** Get Comparator object used in the equals() method to determine
    288    * equality of instructions.
    289    *
    290    * @return currently used comparator for equals()
    291    */
    292   public static InstructionComparator getComparator() { return cmp; }
    293
    294   /*** Set comparator to be used for equals().
    295    */
    296   public static void setComparator(InstructionComparator c) { cmp = c; }
    297
    298   /*** Check for equality, delegated to comparator
    299    * @return true if that is an Instruction and has the same opcode
    300    */
    301   public boolean equals(Object that) {
    302     return (that instanceof Instruction)?
    303       cmp.equals(this, (Instruction)that) : false;
    304   }
    305 }

This page was automatically generated by Maven