KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > bytecode > CodeAttribute


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 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
16 package javassist.bytecode;
17
18 import java.io.DataInputStream JavaDoc;
19 import java.io.DataOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.Map JavaDoc;
24
25 /**
26  * <code>Code_attribute</code>.
27  *
28  * <p>To browse the <code>code</code> field of
29  * a <code>Code_attribute</code> structure,
30  * use <code>CodeIterator</code>.
31  *
32  * @see CodeIterator
33  */

34 public class CodeAttribute extends AttributeInfo implements Opcode {
35     /**
36      * The name of this attribute <code>"Code"</code>.
37      */

38     public static final String JavaDoc tag = "Code";
39
40     // code[] is stored in AttributeInfo.info.
41

42     private int maxStack;
43     private int maxLocals;
44     private ExceptionTable exceptions;
45     private LinkedList JavaDoc attributes;
46
47     /**
48      * Constructs a <code>Code_attribute</code>.
49      *
50      * @param cp constant pool table
51      * @param stack <code>max_stack</code>
52      * @param locals <code>max_locals</code>
53      * @param code <code>code[]</code>
54      * @param etable <code>exception_table[]</code>
55      */

56     public CodeAttribute(ConstPool cp, int stack, int locals, byte[] code,
57                          ExceptionTable etable)
58     {
59         super(cp, tag);
60         maxStack = stack;
61         maxLocals = locals;
62         info = code;
63         exceptions = etable;
64         attributes = new LinkedList JavaDoc();
65     }
66
67     /**
68      * Constructs a copy of <code>Code_attribute</code>.
69      * Specified class names are replaced during the copy.
70      *
71      * @param cp constant pool table.
72      * @param src source Code attribute.
73      * @param classnames pairs of replaced and substituted
74      * class names.
75      */

76     private CodeAttribute(ConstPool cp, CodeAttribute src, Map JavaDoc classnames)
77         throws BadBytecode
78     {
79         super(cp, tag);
80
81         maxStack = src.getMaxStack();
82         maxLocals = src.getMaxLocals();
83         exceptions = src.getExceptionTable().copy(cp, classnames);
84         info = src.copyCode(cp, classnames, exceptions, this);
85
86         attributes = new LinkedList JavaDoc();
87         List JavaDoc src_attr = src.getAttributes();
88         int num = src_attr.size();
89         for (int i = 0; i < num; ++i) {
90             AttributeInfo ai = (AttributeInfo)src_attr.get(i);
91             attributes.add(ai.copy(cp, classnames));
92         }
93     }
94
95     CodeAttribute(ConstPool cp, int name_id, DataInputStream JavaDoc in)
96         throws IOException JavaDoc
97     {
98         super(cp, name_id, (byte[])null);
99         int attr_len = in.readInt();
100
101         maxStack = in.readUnsignedShort();
102         maxLocals = in.readUnsignedShort();
103
104         int code_len = in.readInt();
105         info = new byte[code_len];
106         in.readFully(info);
107
108         exceptions = new ExceptionTable(cp, in);
109
110         attributes = new LinkedList JavaDoc();
111         int num = in.readUnsignedShort();
112         for (int i = 0; i < num; ++i)
113             attributes.add(AttributeInfo.read(cp, in));
114     }
115
116     /**
117      * Makes a copy. Class names are replaced according to the
118      * given <code>Map</code> object.
119      *
120      * @param newCp the constant pool table used by the new copy.
121      * @param classnames pairs of replaced and substituted
122      * class names.
123      * @exception RuntimeCopyException if a <code>BadBytecode</code>
124      * exception is thrown, it is
125      * converted into
126      * <code>RuntimeCopyException</code>.
127      *
128      * @return <code>CodeAttribute</code> object.
129      */

130     public AttributeInfo copy(ConstPool newCp, Map JavaDoc classnames)
131         throws RuntimeCopyException
132     {
133         try {
134             return new CodeAttribute(newCp, this, classnames);
135         }
136         catch (BadBytecode e) {
137             throw new RuntimeCopyException("bad bytecode. fatal?");
138         }
139     }
140
141     /**
142      * An exception that may be thrown by <code>copy()</code>
143      * in <code>CodeAttribute</code>.
144      */

145     public static class RuntimeCopyException extends RuntimeException JavaDoc {
146         /**
147          * Constructs an exception.
148          */

149         public RuntimeCopyException(String JavaDoc s) {
150             super(s);
151         }
152     }
153
154     /**
155      * Returns the length of this <code>attribute_info</code>
156      * structure.
157      * The returned value is <code>attribute_length + 6</code>.
158      */

159     public int length() {
160         return 18 + info.length + exceptions.size() * 8
161                + AttributeInfo.getLength(attributes);
162     }
163
164     void write(DataOutputStream JavaDoc out) throws IOException JavaDoc {
165         out.writeShort(name); // attribute_name_index
166
out.writeInt(length() - 6); // attribute_length
167
out.writeShort(maxStack); // max_stack
168
out.writeShort(maxLocals); // max_locals
169
out.writeInt(info.length); // code_length
170
out.write(info); // code
171
exceptions.write(out);
172         out.writeShort(attributes.size()); // attributes_count
173
AttributeInfo.writeAll(attributes, out); // attributes
174
}
175
176     /**
177      * This method is not available.
178      *
179      * @throws java.lang.UnsupportedOperationException always thrown.
180      */

181     public byte[] get() {
182         throw new UnsupportedOperationException JavaDoc("CodeAttribute.get()");
183     }
184
185     /**
186      * This method is not available.
187      *
188      * @throws java.lang.UnsupportedOperationException always thrown.
189      */

190     public void set(byte[] newinfo) {
191         throw new UnsupportedOperationException JavaDoc("CodeAttribute.set()");
192     }
193
194     /**
195      * Returns the name of the class declaring the method including
196      * this code attribute.
197      */

198     public String JavaDoc getDeclaringClass() {
199         ConstPool cp = getConstPool();
200         return cp.getClassName();
201     }
202
203     /**
204      * Returns <code>max_stack</code>.
205      */

206     public int getMaxStack() {
207         return maxStack;
208     }
209
210     /**
211      * Sets <code>max_stack</code>.
212      */

213     public void setMaxStack(int value) {
214         maxStack = value;
215     }
216
217     /**
218      * Computes the maximum stack size and sets <code>max_stack</code>
219      * to the computed size.
220      *
221      * @throws BadBytecode if this method fails in computing.
222      * @return the newly computed value of <code>max_stack</code>
223      */

224     public int computeMaxStack() throws BadBytecode {
225         maxStack = new CodeAnalyzer(this).computeMaxStack();
226         return maxStack;
227     }
228
229     /**
230      * Returns <code>max_locals</code>.
231      */

232     public int getMaxLocals() {
233         return maxLocals;
234     }
235
236     /**
237      * Sets <code>max_locals</code>.
238      */

239     public void setMaxLocals(int value) {
240         maxLocals = value;
241     }
242
243     /**
244      * Returns <code>code_length</code>.
245      */

246     public int getCodeLength() {
247         return info.length;
248     }
249
250     /**
251      * Returns <code>code[]</code>.
252      */

253     public byte[] getCode() {
254         return info;
255     }
256
257     /**
258      * Sets <code>code[]</code>.
259      */

260     void setCode(byte[] newinfo) { super.set(newinfo); }
261
262     /**
263      * Makes a new iterator for reading this code attribute.
264      */

265     public CodeIterator iterator() {
266         return new CodeIterator(this);
267     }
268
269     /**
270      * Returns <code>exception_table[]</code>.
271      */

272     public ExceptionTable getExceptionTable() { return exceptions; }
273
274     /**
275      * Returns <code>attributes[]</code>.
276      * It returns a list of <code>AttributeInfo</code>.
277      * A new element can be added to the returned list
278      * and an existing element can be removed from the list.
279      *
280      * @see AttributeInfo
281      */

282     public List JavaDoc getAttributes() { return attributes; }
283
284     /**
285      * Returns the attribute with the specified name.
286      * If it is not found, this method returns null.
287      *
288      * @param name attribute name
289      * @return an <code>AttributeInfo</code> object or null.
290      */

291     public AttributeInfo getAttribute(String JavaDoc name) {
292         return AttributeInfo.lookup(attributes, name);
293     }
294
295     /**
296      * Copies code.
297      */

298     private byte[] copyCode(ConstPool destCp, Map JavaDoc classnames,
299                             ExceptionTable etable, CodeAttribute destCa)
300         throws BadBytecode
301     {
302         int len = getCodeLength();
303         byte[] newCode = new byte[len];
304
305         LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
306                                 newCode, destCp, classnames);
307         return LdcEntry.doit(newCode, ldc, etable, destCa);
308     }
309
310     private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
311                                      ConstPool srcCp, byte[] newcode,
312                                      ConstPool destCp, Map JavaDoc classnameMap)
313         throws BadBytecode
314     {
315         int i2, index;
316         LdcEntry ldcEntry = null;
317
318         for (int i = beginPos; i < endPos; i = i2) {
319             i2 = CodeIterator.nextOpcode(code, i);
320             byte c = code[i];
321             newcode[i] = c;
322             switch (c & 0xff) {
323             case LDC_W :
324             case LDC2_W :
325             case GETSTATIC :
326             case PUTSTATIC :
327             case GETFIELD :
328             case PUTFIELD :
329             case INVOKEVIRTUAL :
330             case INVOKESPECIAL :
331             case INVOKESTATIC :
332             case NEW :
333             case ANEWARRAY :
334             case CHECKCAST :
335             case INSTANCEOF :
336                 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
337                                   classnameMap);
338                 break;
339             case LDC :
340                 index = code[i + 1] & 0xff;
341                 index = srcCp.copy(index, destCp, classnameMap);
342                 if (index < 0x100)
343                     newcode[i + 1] = (byte)index;
344                 else {
345                     LdcEntry ldc = new LdcEntry();
346                     ldc.where = i;
347                     ldc.index = index;
348                     ldc.next = ldcEntry;
349                     ldcEntry = ldc;
350                 }
351                 break;
352             case INVOKEINTERFACE :
353                 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
354                                   classnameMap);
355                 newcode[i + 3] = code[i + 3];
356                 newcode[i + 4] = code[i + 4];
357                 break;
358             case MULTIANEWARRAY :
359                 copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
360                                   classnameMap);
361                 newcode[i + 3] = code[i + 3];
362                 break;
363             default :
364                 while (++i < i2)
365                     newcode[i] = code[i];
366
367                 break;
368             }
369         }
370
371         return ldcEntry;
372     }
373
374     private static void copyConstPoolInfo(int i, byte[] code, ConstPool srcCp,
375                                           byte[] newcode, ConstPool destCp,
376                                           Map JavaDoc classnameMap) {
377         int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff);
378         index = srcCp.copy(index, destCp, classnameMap);
379         newcode[i] = (byte)(index >> 8);
380         newcode[i + 1] = (byte)index;
381     }
382 }
383
384 final class LdcEntry {
385     LdcEntry next;
386     int where;
387     int index;
388
389     static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable,
390                        CodeAttribute ca)
391         throws BadBytecode
392     {
393         while (ldc != null) {
394             int where = ldc.where;
395             code = CodeIterator.insertGap(code, where, 1, false, etable, ca);
396             code[where] = (byte)Opcode.LDC_W;
397             ByteArray.write16bit(ldc.index, code, where + 1);
398             ldc = ldc.next;
399         }
400
401         return code;
402     }
403 }
404
Popular Tags