You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LocalVariableAttribute.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later,
  9. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.bytecode;
  17. import java.io.DataInputStream;
  18. import java.io.IOException;
  19. import java.util.Map;
  20. /**
  21. * <code>LocalVariableTable_attribute</code>.
  22. */
  23. public class LocalVariableAttribute extends AttributeInfo {
  24. /**
  25. * The name of this attribute <code>"LocalVariableTable"</code>.
  26. */
  27. public static final String tag = "LocalVariableTable";
  28. /**
  29. * The name of the attribute <code>"LocalVariableTypeTable"</code>.
  30. */
  31. public static final String typeTag = "LocalVariableTypeTable";
  32. /**
  33. * Constructs an empty LocalVariableTable.
  34. */
  35. public LocalVariableAttribute(ConstPool cp) {
  36. super(cp, tag, new byte[2]);
  37. ByteArray.write16bit(0, info, 0);
  38. }
  39. /**
  40. * Constructs an empty LocalVariableTable.
  41. *
  42. * @param name the attribute name.
  43. * <code>LocalVariableAttribute.tag</code> or
  44. * <code>LocalVariableAttribute.typeTag</code>.
  45. * @see #tag
  46. * @see #typeTag
  47. * @since 3.1
  48. * @deprecated
  49. */
  50. public LocalVariableAttribute(ConstPool cp, String name) {
  51. super(cp, name, new byte[2]);
  52. ByteArray.write16bit(0, info, 0);
  53. }
  54. LocalVariableAttribute(ConstPool cp, int n, DataInputStream in)
  55. throws IOException
  56. {
  57. super(cp, n, in);
  58. }
  59. LocalVariableAttribute(ConstPool cp, String name, byte[] i) {
  60. super(cp, name, i);
  61. }
  62. /**
  63. * Appends a new entry to <code>local_variable_table</code>.
  64. *
  65. * @param startPc <code>start_pc</code>
  66. * @param length <code>length</code>
  67. * @param nameIndex <code>name_index</code>
  68. * @param descriptorIndex <code>descriptor_index</code>
  69. * @param index <code>index</code>
  70. */
  71. public void addEntry(int startPc, int length, int nameIndex,
  72. int descriptorIndex, int index) {
  73. int size = info.length;
  74. byte[] newInfo = new byte[size + 10];
  75. ByteArray.write16bit(tableLength() + 1, newInfo, 0);
  76. for (int i = 2; i < size; ++i)
  77. newInfo[i] = info[i];
  78. ByteArray.write16bit(startPc, newInfo, size);
  79. ByteArray.write16bit(length, newInfo, size + 2);
  80. ByteArray.write16bit(nameIndex, newInfo, size + 4);
  81. ByteArray.write16bit(descriptorIndex, newInfo, size + 6);
  82. ByteArray.write16bit(index, newInfo, size + 8);
  83. info = newInfo;
  84. }
  85. void renameClass(String oldname, String newname) {
  86. ConstPool cp = getConstPool();
  87. int n = tableLength();
  88. for (int i = 0; i < n; ++i) {
  89. int pos = i * 10 + 2;
  90. int index = ByteArray.readU16bit(info, pos + 6);
  91. if (index != 0) {
  92. String desc = cp.getUtf8Info(index);
  93. desc = renameEntry(desc, oldname, newname);
  94. ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
  95. }
  96. }
  97. }
  98. String renameEntry(String desc, String oldname, String newname) {
  99. return Descriptor.rename(desc, oldname, newname);
  100. }
  101. void renameClass(Map classnames) {
  102. ConstPool cp = getConstPool();
  103. int n = tableLength();
  104. for (int i = 0; i < n; ++i) {
  105. int pos = i * 10 + 2;
  106. int index = ByteArray.readU16bit(info, pos + 6);
  107. if (index != 0) {
  108. String desc = cp.getUtf8Info(index);
  109. desc = renameEntry(desc, classnames);
  110. ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
  111. }
  112. }
  113. }
  114. String renameEntry(String desc, Map classnames) {
  115. return Descriptor.rename(desc, classnames);
  116. }
  117. /**
  118. * For each <code>local_variable_table[i].index</code>,
  119. * this method increases <code>index</code> by <code>delta</code>.
  120. *
  121. * @param lessThan the index does not change if it
  122. * is less than this value.
  123. */
  124. public void shiftIndex(int lessThan, int delta) {
  125. int size = info.length;
  126. for (int i = 2; i < size; i += 10){
  127. int org = ByteArray.readU16bit(info, i + 8);
  128. if (org >= lessThan)
  129. ByteArray.write16bit(org + delta, info, i + 8);
  130. }
  131. }
  132. /**
  133. * Returns <code>local_variable_table_length</code>.
  134. * This represents the number of entries in the table.
  135. */
  136. public int tableLength() {
  137. return ByteArray.readU16bit(info, 0);
  138. }
  139. /**
  140. * Returns <code>local_variable_table[i].start_pc</code>.
  141. * This represents the index into the code array from which the local
  142. * variable is effective.
  143. *
  144. * @param i the i-th entry.
  145. */
  146. public int startPc(int i) {
  147. return ByteArray.readU16bit(info, i * 10 + 2);
  148. }
  149. /**
  150. * Returns <code>local_variable_table[i].length</code>.
  151. * This represents the length of the code region in which the local
  152. * variable is effective.
  153. *
  154. * @param i the i-th entry.
  155. */
  156. public int codeLength(int i) {
  157. return ByteArray.readU16bit(info, i * 10 + 4);
  158. }
  159. /**
  160. * Adjusts start_pc and length if bytecode is inserted in a method body.
  161. */
  162. void shiftPc(int where, int gapLength, boolean exclusive) {
  163. int n = tableLength();
  164. for (int i = 0; i < n; ++i) {
  165. int pos = i * 10 + 2;
  166. int pc = ByteArray.readU16bit(info, pos);
  167. int len = ByteArray.readU16bit(info, pos + 2);
  168. /* if pc == 0, then the local variable is a method parameter.
  169. */
  170. if (pc > where || (exclusive && pc == where && pc != 0))
  171. ByteArray.write16bit(pc + gapLength, info, pos);
  172. else if (pc + len > where || (exclusive && pc + len == where))
  173. ByteArray.write16bit(len + gapLength, info, pos + 2);
  174. }
  175. }
  176. /**
  177. * Returns the value of <code>local_variable_table[i].name_index</code>.
  178. * This represents the name of the local variable.
  179. *
  180. * @param i the i-th entry.
  181. */
  182. public int nameIndex(int i) {
  183. return ByteArray.readU16bit(info, i * 10 + 6);
  184. }
  185. /**
  186. * Returns the name of the local variable
  187. * specified by <code>local_variable_table[i].name_index</code>.
  188. *
  189. * @param i the i-th entry.
  190. */
  191. public String variableName(int i) {
  192. return getConstPool().getUtf8Info(nameIndex(i));
  193. }
  194. /**
  195. * Returns the value of
  196. * <code>local_variable_table[i].descriptor_index</code>.
  197. * This represents the type descriptor of the local variable.
  198. * <p>
  199. * If this attribute represents a LocalVariableTypeTable attribute,
  200. * this method returns the value of
  201. * <code>local_variable_type_table[i].signature_index</code>.
  202. * It represents the type of the local variable.
  203. *
  204. * @param i the i-th entry.
  205. */
  206. public int descriptorIndex(int i) {
  207. return ByteArray.readU16bit(info, i * 10 + 8);
  208. }
  209. /**
  210. * This method is equivalent to <code>descriptorIndex()</code>.
  211. * If this attribute represents a LocalVariableTypeTable attribute,
  212. * this method should be used instead of <code>descriptorIndex()</code>
  213. * since the method name is more appropriate.
  214. *
  215. * @param i the i-th entry.
  216. * @see #descriptorIndex(int)
  217. * @see SignatureAttribute#toFieldSignature(String)
  218. */
  219. public int signatureIndex(int i) {
  220. return descriptorIndex(i);
  221. }
  222. /**
  223. * Returns the type descriptor of the local variable
  224. * specified by <code>local_variable_table[i].descriptor_index</code>.
  225. * <p>
  226. * If this attribute represents a LocalVariableTypeTable attribute,
  227. * this method returns the type signature of the local variable
  228. * specified by <code>local_variable_type_table[i].signature_index</code>.
  229. *
  230. * @param i the i-th entry.
  231. */
  232. public String descriptor(int i) {
  233. return getConstPool().getUtf8Info(descriptorIndex(i));
  234. }
  235. /**
  236. * This method is equivalent to <code>descriptor()</code>.
  237. * If this attribute represents a LocalVariableTypeTable attribute,
  238. * this method should be used instead of <code>descriptor()</code>
  239. * since the method name is more appropriate.
  240. *
  241. * <p>To parse the string, call <code>toFieldSignature(String)</code>
  242. * in <code>SignatureAttribute</code>.
  243. *
  244. * @param i the i-th entry.
  245. * @see #descriptor(int)
  246. * @see SignatureAttribute#toFieldSignature(String)
  247. */
  248. public String signature(int i) {
  249. return descriptor(i);
  250. }
  251. /**
  252. * Returns <code>local_variable_table[i].index</code>.
  253. * This represents the index of the local variable.
  254. *
  255. * @param i the i-th entry.
  256. */
  257. public int index(int i) {
  258. return ByteArray.readU16bit(info, i * 10 + 10);
  259. }
  260. /**
  261. * Makes a copy.
  262. *
  263. * @param newCp the constant pool table used by the new copy.
  264. * @param classnames should be null.
  265. */
  266. public AttributeInfo copy(ConstPool newCp, Map classnames) {
  267. byte[] src = get();
  268. byte[] dest = new byte[src.length];
  269. ConstPool cp = getConstPool();
  270. LocalVariableAttribute attr = makeThisAttr(newCp, dest);
  271. int n = ByteArray.readU16bit(src, 0);
  272. ByteArray.write16bit(n, dest, 0);
  273. int j = 2;
  274. for (int i = 0; i < n; ++i) {
  275. int start = ByteArray.readU16bit(src, j);
  276. int len = ByteArray.readU16bit(src, j + 2);
  277. int name = ByteArray.readU16bit(src, j + 4);
  278. int type = ByteArray.readU16bit(src, j + 6);
  279. int index = ByteArray.readU16bit(src, j + 8);
  280. ByteArray.write16bit(start, dest, j);
  281. ByteArray.write16bit(len, dest, j + 2);
  282. if (name != 0)
  283. name = cp.copy(name, newCp, null);
  284. ByteArray.write16bit(name, dest, j + 4);
  285. if (type != 0) {
  286. String sig = cp.getUtf8Info(type);
  287. sig = Descriptor.rename(sig, classnames);
  288. type = newCp.addUtf8Info(sig);
  289. }
  290. ByteArray.write16bit(type, dest, j + 6);
  291. ByteArray.write16bit(index, dest, j + 8);
  292. j += 10;
  293. }
  294. return attr;
  295. }
  296. // LocalVariableTypeAttribute overrides this method.
  297. LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
  298. return new LocalVariableAttribute(cp, tag, dest);
  299. }
  300. }