001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024 025import org.apache.bcel.Constants; 026import org.apache.bcel.util.Args; 027 028/** 029 * This class represents a local variable within a method. It contains its scope, name, signature and index on the 030 * method's frame. It is used both to represent an element of the LocalVariableTable as well as an element of the 031 * LocalVariableTypeTable. The nomenclature used here may be a bit confusing; while the two items have the same layout 032 * in a class file, a LocalVariableTable attribute contains a descriptor_index, not a signatureIndex. The 033 * LocalVariableTypeTable attribute does have a signatureIndex. 034 * 035 * @see org.apache.bcel.classfile.Utility for more details on the difference. 036 * @see LocalVariableTable 037 * @see LocalVariableTypeTable 038 */ 039public final class LocalVariable implements Cloneable, Node, Constants { 040 041 static final LocalVariable[] EMPTY_ARRAY = {}; 042 043 /** Range in which the variable is valid. */ 044 private int startPc; 045 046 private int length; 047 048 /** Index in constant pool of variable name. */ 049 private int nameIndex; 050 051 /** 052 * Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature 053 */ 054 private int signatureIndex; 055 056 /* 057 * Variable is index'th local variable on this method's frame. 058 */ 059 private int index; 060 061 private ConstantPool constantPool; 062 063 /** Never changes; used to match up with LocalVariableTypeTable entries. */ 064 private final int origIndex; 065 066 /** 067 * Constructs object from file stream. 068 * 069 * @param file Input stream. 070 * @throws IOException if an I/O error occurs. 071 */ 072 LocalVariable(final DataInput file, final ConstantPool constantPool) throws IOException { 073 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), constantPool); 074 } 075 076 /** 077 * Constructs a LocalVariable. 078 * 079 * @param startPc Range in which the variable is valid. 080 * @param length length of validity. 081 * @param nameIndex Index in constant pool of variable name. 082 * @param signatureIndex Index of variable's signature. 083 * @param index Variable is 'index'th local variable on the method's frame. 084 * @param constantPool Array of constants. 085 */ 086 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool) { 087 this(startPc, length, nameIndex, signatureIndex, index, constantPool, index); 088 } 089 090 /** 091 * Constructs a LocalVariable. 092 * 093 * @param startPc Range in which the variable is valid. 094 * @param length length of validity. 095 * @param nameIndex Index in constant pool of variable name. 096 * @param signatureIndex Index of variable's signature. 097 * @param index Variable is 'index'th local variable on the method's frame. 098 * @param constantPool Array of constants. 099 * @param origIndex Variable is 'index'th local variable on the method's frame prior to any changes. 100 */ 101 public LocalVariable(final int startPc, final int length, final int nameIndex, final int signatureIndex, final int index, final ConstantPool constantPool, 102 final int origIndex) { 103 this.startPc = Args.requireU2(startPc, "startPc"); 104 this.length = Args.requireU2(length, "length"); 105 this.nameIndex = Args.requireU2(nameIndex, "nameIndex"); 106 this.signatureIndex = Args.requireU2(signatureIndex, "signatureIndex"); 107 this.index = Args.requireU2(index, "index"); 108 this.origIndex = Args.requireU2(origIndex, "origIndex"); 109 this.constantPool = constantPool; 110 } 111 112 /** 113 * Initializes from another LocalVariable. Note that both objects use the same references (shallow copy). Use copy() for 114 * a physical copy. 115 * 116 * @param localVariable Another LocalVariable. 117 */ 118 public LocalVariable(final LocalVariable localVariable) { 119 this(localVariable.getStartPC(), localVariable.getLength(), localVariable.getNameIndex(), localVariable.getSignatureIndex(), localVariable.getIndex(), 120 localVariable.getConstantPool()); 121 } 122 123 /** 124 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 125 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 126 * 127 * @param v Visitor object. 128 */ 129 @Override 130 public void accept(final Visitor v) { 131 v.visitLocalVariable(this); 132 } 133 134 /** 135 * Creates a deep copy of this object. 136 * 137 * @return deep copy of this object. 138 */ 139 public LocalVariable copy() { 140 try { 141 return (LocalVariable) clone(); 142 } catch (final CloneNotSupportedException e) { 143 // TODO should this throw? 144 } 145 return null; 146 } 147 148 /** 149 * Dumps local variable to file stream in binary format. 150 * 151 * @param dataOutputStream Output file stream. 152 * @throws IOException if an I/O error occurs. 153 * @see java.io.FilterOutputStream#out 154 */ 155 public void dump(final DataOutputStream dataOutputStream) throws IOException { 156 dataOutputStream.writeShort(startPc); 157 dataOutputStream.writeShort(length); 158 dataOutputStream.writeShort(nameIndex); 159 dataOutputStream.writeShort(signatureIndex); 160 dataOutputStream.writeShort(index); 161 } 162 163 /** 164 * Gets the constant pool used by this object. 165 * 166 * @return Constant pool used by this object. 167 */ 168 public ConstantPool getConstantPool() { 169 return constantPool; 170 } 171 172 /** 173 * Gets the index of register where variable is stored. 174 * 175 * @return index of register where variable is stored. 176 */ 177 public int getIndex() { 178 return index; 179 } 180 181 /** 182 * Gets the length of validity. 183 * 184 * @return Variable is valid within getStartPC() .. getStartPC()+getLength(). 185 */ 186 public int getLength() { 187 return length; 188 } 189 190 /** 191 * Gets the variable name. 192 * 193 * @return Variable name. 194 */ 195 public String getName() { 196 return constantPool.getConstantUtf8(nameIndex).getBytes(); 197 } 198 199 /** 200 * Gets the index in constant pool of variable name. 201 * 202 * @return Index in constant pool of variable name. 203 */ 204 public int getNameIndex() { 205 return nameIndex; 206 } 207 208 /** 209 * Gets the index of register where variable was originally stored. 210 * 211 * @return index of register where variable was originally stored. 212 */ 213 public int getOrigIndex() { 214 return origIndex; 215 } 216 217 /** 218 * Gets the signature. 219 * 220 * @return Signature. 221 */ 222 public String getSignature() { 223 return constantPool.getConstantUtf8(signatureIndex).getBytes(); 224 } 225 226 /** 227 * Gets the index in constant pool of variable signature. 228 * 229 * @return Index in constant pool of variable signature. 230 */ 231 public int getSignatureIndex() { 232 return signatureIndex; 233 } 234 235 /** 236 * Gets the start of range where the variable is valid. 237 * 238 * @return Start of range where the variable is valid. 239 */ 240 public int getStartPC() { 241 return startPc; 242 } 243 244 /** 245 * Sets the constant pool to be used for this object. 246 * 247 * @param constantPool Constant pool to be used for this object. 248 */ 249 public void setConstantPool(final ConstantPool constantPool) { 250 this.constantPool = constantPool; 251 } 252 253 /** 254 * Sets the index in the local variable table of this variable. 255 * 256 * @param index the index in the local variable table of this variable. 257 */ 258 public void setIndex(final int index) { // TODO unused 259 this.index = index; 260 } 261 262 /** 263 * Sets the length of this local variable. 264 * 265 * @param length the length of this local variable. 266 */ 267 public void setLength(final int length) { 268 this.length = length; 269 } 270 271 /** 272 * Sets the index into the constant pool for the name of this variable. 273 * 274 * @param nameIndex the index into the constant pool for the name of this variable. 275 */ 276 public void setNameIndex(final int nameIndex) { // TODO unused 277 this.nameIndex = nameIndex; 278 } 279 280 /** 281 * Sets the index into the constant pool for the signature of this variable. 282 * 283 * @param signatureIndex the index into the constant pool for the signature of this variable. 284 */ 285 public void setSignatureIndex(final int signatureIndex) { // TODO unused 286 this.signatureIndex = signatureIndex; 287 } 288 289 /** 290 * Sets the range where the local variable is valid. 291 * 292 * @param startPc Specify range where the local variable is valid. 293 */ 294 public void setStartPC(final int startPc) { // TODO unused 295 this.startPc = startPc; 296 } 297 298 /** 299 * Gets the string representation. 300 * 301 * @return string representation. 302 */ 303 @Override 304 public String toString() { 305 return toStringShared(false); 306 } 307 308 /* 309 * Helper method shared with LocalVariableTypeTable 310 */ 311 String toStringShared(final boolean typeTable) { 312 final String name = getName(); 313 final String signature = Utility.signatureToString(getSignature(), false); 314 final String label = "LocalVariable" + (typeTable ? "Types" : ""); 315 return label + "(startPc = " + startPc + ", length = " + length + ", index = " + index + ":" + signature + " " + name + ")"; 316 } 317} 318