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