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

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