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.

CodeAttribute.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2003 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. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist.bytecode;
  16. import java.io.DataInputStream;
  17. import java.io.DataOutputStream;
  18. import java.io.IOException;
  19. import java.util.List;
  20. import java.util.LinkedList;
  21. import java.util.Map;
  22. /**
  23. * <code>Code_attribute</code>.
  24. *
  25. * <p>To browse the <code>code</code> field of
  26. * a <code>Code_attribute</code> structure,
  27. * use <code>CodeIterator</code>.
  28. *
  29. * @see CodeIterator
  30. */
  31. public class CodeAttribute extends AttributeInfo implements Opcode {
  32. /**
  33. * The name of this attribute <code>"Code"</code>.
  34. */
  35. public static final String tag = "Code";
  36. // code[] is stored in AttributeInfo.info.
  37. private int maxStack;
  38. private int maxLocals;
  39. private ExceptionTable exceptions;
  40. private LinkedList attributes;
  41. /**
  42. * Constructs a <code>Code_attribute</code>.
  43. *
  44. * @param cp constant pool table
  45. * @param stack <code>max_stack</code>
  46. * @param locals <code>max_locals</code>
  47. * @param code <code>code[]</code>
  48. * @param etable <code>exception_table[]</code>
  49. */
  50. public CodeAttribute(ConstPool cp, int stack, int locals, byte[] code,
  51. ExceptionTable etable)
  52. {
  53. super(cp, tag);
  54. maxStack = stack;
  55. maxLocals = locals;
  56. info = code;
  57. exceptions = etable;
  58. attributes = new LinkedList();
  59. }
  60. /**
  61. * Constructs a copy of <code>Code_attribute</code>.
  62. * Specified class names are replaced during the copy.
  63. *
  64. * @param cp constant pool table.
  65. * @param src source Code attribute.
  66. * @param classnames pairs of replaced and substituted
  67. * class names.
  68. */
  69. private CodeAttribute(ConstPool cp, CodeAttribute src, Map classnames)
  70. throws BadBytecode
  71. {
  72. super(cp, tag);
  73. maxStack = src.getMaxStack();
  74. maxLocals = src.getMaxLocals();
  75. exceptions = src.getExceptionTable().copy(cp, classnames);
  76. info = src.copyCode(cp, classnames, exceptions);
  77. attributes = new LinkedList();
  78. /* Since an index into the source constant pool table may not
  79. be translated, we don't copy the attributes.
  80. */
  81. /*
  82. List src_attr = src.getAttributes();
  83. int num = src_attr.size();
  84. for (int i = 0; i < num; ++i) {
  85. AttributeInfo ai = (AttributeInfo)src_attr.get(i);
  86. attributes.add(ai.copy(cp, classnames));
  87. }
  88. */
  89. }
  90. CodeAttribute(ConstPool cp, int name_id, DataInputStream in)
  91. throws IOException
  92. {
  93. super(cp, name_id, (byte[])null);
  94. int attr_len = in.readInt();
  95. maxStack = in.readUnsignedShort();
  96. maxLocals = in.readUnsignedShort();
  97. int code_len = in.readInt();
  98. info = new byte[code_len];
  99. in.readFully(info);
  100. exceptions = new ExceptionTable(cp, in);
  101. attributes = new LinkedList();
  102. int num = in.readUnsignedShort();
  103. for (int i = 0; i < num; ++i)
  104. attributes.add(AttributeInfo.read(cp, in));
  105. }
  106. /**
  107. * Makes a copy. Class names are replaced according to the
  108. * given <code>Map</code> object.
  109. *
  110. * @param newCp the constant pool table used by the new copy.
  111. * @param classnames pairs of replaced and substituted
  112. * class names.
  113. * @exception RuntimeCopyException if a <code>BadBytecode</code>
  114. * exception is thrown, it is
  115. * converted into
  116. * <code>RuntimeCopyException</code>.
  117. *
  118. * @return <code>CodeAttribute</code> object.
  119. */
  120. public AttributeInfo copy(ConstPool newCp, Map classnames)
  121. throws RuntimeCopyException
  122. {
  123. try {
  124. return new CodeAttribute(newCp, this, classnames);
  125. }
  126. catch (BadBytecode e) {
  127. throw new RuntimeCopyException("bad bytecode. fatal?");
  128. }
  129. }
  130. /**
  131. * An exception that may be thrown by <code>copy()</code>
  132. * in <code>CodeAttribute</code>.
  133. */
  134. public static class RuntimeCopyException extends RuntimeException {
  135. /**
  136. * Constructs an exception.
  137. */
  138. public RuntimeCopyException(String s) {
  139. super(s);
  140. }
  141. }
  142. /**
  143. * Returns the length of this <code>attribute_info</code>
  144. * structure.
  145. * The returned value is <code>attribute_length + 6</code>.
  146. */
  147. public int length() {
  148. return 18 + info.length + exceptions.size() * 8
  149. + AttributeInfo.getLength(attributes);
  150. }
  151. void write(DataOutputStream out) throws IOException {
  152. out.writeShort(name); // attribute_name_index
  153. out.writeInt(length() - 6); // attribute_length
  154. out.writeShort(maxStack); // max_stack
  155. out.writeShort(maxLocals); // max_locals
  156. out.writeInt(info.length); // code_length
  157. out.write(info); // code
  158. exceptions.write(out);
  159. out.writeShort(attributes.size()); // attributes_count
  160. AttributeInfo.writeAll(attributes, out); // attributes
  161. }
  162. /**
  163. * This method is not available.
  164. *
  165. * @throws java.lang.UnsupportedOperationException always thrown.
  166. */
  167. public byte[] get() {
  168. throw new UnsupportedOperationException("CodeAttribute.get()");
  169. }
  170. /**
  171. * This method is not available.
  172. *
  173. * @throws java.lang.UnsupportedOperationException always thrown.
  174. */
  175. public void set(byte[] newinfo) {
  176. throw new UnsupportedOperationException("CodeAttribute.set()");
  177. }
  178. /**
  179. * Returns the name of the class declaring the method including
  180. * this code attribute.
  181. */
  182. public String getDeclaringClass() {
  183. ConstPool cp = getConstPool();
  184. return cp.getClassName();
  185. }
  186. /**
  187. * Returns <code>max_stack</code>.
  188. */
  189. public int getMaxStack() {
  190. return maxStack;
  191. }
  192. /**
  193. * Sets <code>max_stack</code>.
  194. */
  195. public void setMaxStack(int value) {
  196. maxStack = value;
  197. }
  198. /**
  199. * Returns <code>max_locals</code>.
  200. */
  201. public int getMaxLocals() {
  202. return maxLocals;
  203. }
  204. /**
  205. * Sets <code>max_locals</code>.
  206. */
  207. public void setMaxLocals(int value) {
  208. maxLocals = value;
  209. }
  210. /**
  211. * Returns <code>code_length</code>.
  212. */
  213. public int getCodeLength() {
  214. return info.length;
  215. }
  216. /**
  217. * Returns <code>code[]</code>.
  218. */
  219. public byte[] getCode() {
  220. return info;
  221. }
  222. /**
  223. * Sets <code>code[]</code>.
  224. */
  225. void setCode(byte[] newinfo) { super.set(newinfo); }
  226. /**
  227. * Makes a new iterator for reading this code attribute.
  228. */
  229. public CodeIterator iterator() {
  230. return new CodeIterator(this);
  231. }
  232. /**
  233. * Returns <code>exception_table[]</code>.
  234. */
  235. public ExceptionTable getExceptionTable() { return exceptions; }
  236. /**
  237. * Returns <code>attributes[]</code>.
  238. * It returns a list of <code>AttributeInfo</code>.
  239. *
  240. * @see AttributeInfo
  241. */
  242. public List getAttributes() { return attributes; }
  243. /**
  244. * Returns the attribute with the specified name.
  245. * If it is not found, this method returns null.
  246. *
  247. * @param name attribute name
  248. * @return an <code>AttributeInfo</code> object or null.
  249. */
  250. public AttributeInfo getAttribute(String name) {
  251. return AttributeInfo.lookup(attributes, name);
  252. }
  253. /**
  254. * Copies code.
  255. */
  256. private byte[] copyCode(ConstPool destCp, Map classnames,
  257. ExceptionTable etable)
  258. throws BadBytecode
  259. {
  260. int len = getCodeLength();
  261. byte[] newCode = new byte[len];
  262. LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
  263. newCode, destCp, classnames);
  264. return LdcEntry.doit(newCode, ldc, etable);
  265. }
  266. private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
  267. ConstPool srcCp, byte[] newcode,
  268. ConstPool destCp, Map classnameMap)
  269. throws BadBytecode
  270. {
  271. int i2, index;
  272. LdcEntry ldcEntry = null;
  273. for (int i = beginPos; i < endPos; i = i2) {
  274. i2 = CodeIterator.nextOpcode(code, i);
  275. byte c = code[i];
  276. newcode[i] = c;
  277. switch (c & 0xff) {
  278. case LDC_W :
  279. case LDC2_W :
  280. case GETSTATIC :
  281. case PUTSTATIC :
  282. case GETFIELD :
  283. case PUTFIELD :
  284. case INVOKEVIRTUAL :
  285. case INVOKESPECIAL :
  286. case INVOKESTATIC :
  287. case NEW :
  288. case ANEWARRAY :
  289. case CHECKCAST :
  290. case INSTANCEOF :
  291. copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
  292. classnameMap);
  293. break;
  294. case LDC :
  295. index = code[i + 1] & 0xff;
  296. index = srcCp.copy(index, destCp, classnameMap);
  297. if (index < 0x100)
  298. newcode[i + 1] = (byte)index;
  299. else {
  300. LdcEntry ldc = new LdcEntry();
  301. ldc.where = i;
  302. ldc.index = index;
  303. ldc.next = ldcEntry;
  304. ldcEntry = ldc;
  305. }
  306. break;
  307. case INVOKEINTERFACE :
  308. copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
  309. classnameMap);
  310. newcode[i + 3] = code[i + 3];
  311. newcode[i + 4] = code[i + 4];
  312. break;
  313. case MULTIANEWARRAY :
  314. copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
  315. classnameMap);
  316. newcode[i + 3] = code[i + 3];
  317. break;
  318. default :
  319. while (++i < i2)
  320. newcode[i] = code[i];
  321. break;
  322. }
  323. }
  324. return ldcEntry;
  325. }
  326. private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp,
  327. byte[] newcode, ConstPool destCp,
  328. Map classnameMap) {
  329. int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff);
  330. index = srcCp.copy(index, destCp, classnameMap);
  331. newcode[i] = (byte)(index >> 8);
  332. newcode[i + 1] = (byte)index;
  333. }
  334. }
  335. final class LdcEntry {
  336. LdcEntry next;
  337. int where;
  338. int index;
  339. static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable)
  340. throws BadBytecode
  341. {
  342. while (ldc != null) {
  343. int where = ldc.where;
  344. code = CodeIterator.insertGap(code, where, 1, false, etable);
  345. code[where] = (byte)Opcode.LDC_W;
  346. ByteArray.write16bit(ldc.index, code, where + 1);
  347. ldc = ldc.next;
  348. }
  349. return code;
  350. }
  351. }