KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > classfile > Code


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.classfile;
18
19 import java.io.DataInputStream JavaDoc;
20 import java.io.DataOutputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import org.apache.bcel.Constants;
23
24 /**
25  * This class represents a chunk of Java byte code contained in a
26  * method. It is instantiated by the
27  * <em>Attribute.readAttribute()</em> method. A <em>Code</em>
28  * attribute contains informations about operand stack, local
29  * variables, byte code and the exceptions handled within this
30  * method.
31  *
32  * This attribute has attributes itself, namely <em>LineNumberTable</em> which
33  * is used for debugging purposes and <em>LocalVariableTable</em> which
34  * contains information about the local variables.
35  *
36  * @version $Id: Code.java 386056 2006-03-15 11:31:56Z tcurdt $
37  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
38  * @see Attribute
39  * @see CodeException
40  * @see LineNumberTable
41  * @see LocalVariableTable
42  */

43 public final class Code extends Attribute {
44
45     private int max_stack; // Maximum size of stack used by this method
46
private int max_locals; // Number of local variables
47
private int code_length; // Length of code in bytes
48
private byte[] code; // Actual byte code
49
private int exception_table_length;
50     private CodeException[] exception_table; // Table of handled exceptions
51
private int attributes_count; // Attributes of code: LineNumber
52
private Attribute[] attributes; // or LocalVariable
53

54
55     /**
56      * Initialize from another object. Note that both objects use the same
57      * references (shallow copy). Use copy() for a physical copy.
58      */

59     public Code(Code c) {
60         this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c
61                 .getExceptionTable(), c.getAttributes(), c.getConstantPool());
62     }
63
64
65     /**
66      * @param name_index Index pointing to the name <em>Code</em>
67      * @param length Content length in bytes
68      * @param file Input stream
69      * @param constant_pool Array of constants
70      */

71     Code(int name_index, int length, DataInputStream JavaDoc file, ConstantPool constant_pool)
72             throws IOException JavaDoc {
73         // Initialize with some default values which will be overwritten later
74
this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null,
75                 (CodeException[]) null, (Attribute[]) null, constant_pool);
76         code_length = file.readInt();
77         code = new byte[code_length]; // Read byte code
78
file.readFully(code);
79         /* Read exception table that contains all regions where an exception
80          * handler is active, i.e., a try { ... } catch() block.
81          */

82         exception_table_length = file.readUnsignedShort();
83         exception_table = new CodeException[exception_table_length];
84         for (int i = 0; i < exception_table_length; i++) {
85             exception_table[i] = new CodeException(file);
86         }
87         /* Read all attributes, currently `LineNumberTable' and
88          * `LocalVariableTable'
89          */

90         attributes_count = file.readUnsignedShort();
91         attributes = new Attribute[attributes_count];
92         for (int i = 0; i < attributes_count; i++) {
93             attributes[i] = Attribute.readAttribute(file, constant_pool);
94         }
95         /* Adjust length, because of setAttributes in this(), s.b. length
96          * is incorrect, because it didn't take the internal attributes
97          * into account yet! Very subtle bug, fixed in 3.1.1.
98          */

99         this.length = length;
100     }
101
102
103     /**
104      * @param name_index Index pointing to the name <em>Code</em>
105      * @param length Content length in bytes
106      * @param max_stack Maximum size of stack
107      * @param max_locals Number of local variables
108      * @param code Actual byte code
109      * @param exception_table Table of handled exceptions
110      * @param attributes Attributes of code: LineNumber or LocalVariable
111      * @param constant_pool Array of constants
112      */

113     public Code(int name_index, int length, int max_stack, int max_locals, byte[] code,
114             CodeException[] exception_table, Attribute[] attributes, ConstantPool constant_pool) {
115         super(Constants.ATTR_CODE, name_index, length, constant_pool);
116         this.max_stack = max_stack;
117         this.max_locals = max_locals;
118         setCode(code);
119         setExceptionTable(exception_table);
120         setAttributes(attributes); // Overwrites length!
121
}
122
123
124     /**
125      * Called by objects that are traversing the nodes of the tree implicitely
126      * defined by the contents of a Java class. I.e., the hierarchy of methods,
127      * fields, attributes, etc. spawns a tree of objects.
128      *
129      * @param v Visitor object
130      */

131     public void accept( Visitor v ) {
132         v.visitCode(this);
133     }
134
135
136     /**
137      * Dump code attribute to file stream in binary format.
138      *
139      * @param file Output file stream
140      * @throws IOException
141      */

142     public final void dump( DataOutputStream JavaDoc file ) throws IOException JavaDoc {
143         super.dump(file);
144         file.writeShort(max_stack);
145         file.writeShort(max_locals);
146         file.writeInt(code_length);
147         file.write(code, 0, code_length);
148         file.writeShort(exception_table_length);
149         for (int i = 0; i < exception_table_length; i++) {
150             exception_table[i].dump(file);
151         }
152         file.writeShort(attributes_count);
153         for (int i = 0; i < attributes_count; i++) {
154             attributes[i].dump(file);
155         }
156     }
157
158
159     /**
160      * @return Collection of code attributes.
161      * @see Attribute
162      */

163     public final Attribute[] getAttributes() {
164         return attributes;
165     }
166
167
168     /**
169      * @return LineNumberTable of Code, if it has one
170      */

171     public LineNumberTable getLineNumberTable() {
172         for (int i = 0; i < attributes_count; i++) {
173             if (attributes[i] instanceof LineNumberTable) {
174                 return (LineNumberTable) attributes[i];
175             }
176         }
177         return null;
178     }
179
180
181     /**
182      * @return LocalVariableTable of Code, if it has one
183      */

184     public LocalVariableTable getLocalVariableTable() {
185         for (int i = 0; i < attributes_count; i++) {
186             if (attributes[i] instanceof LocalVariableTable) {
187                 return (LocalVariableTable) attributes[i];
188             }
189         }
190         return null;
191     }
192
193
194     /**
195      * @return Actual byte code of the method.
196      */

197     public final byte[] getCode() {
198         return code;
199     }
200
201
202     /**
203      * @return Table of handled exceptions.
204      * @see CodeException
205      */

206     public final CodeException[] getExceptionTable() {
207         return exception_table;
208     }
209
210
211     /**
212      * @return Number of local variables.
213      */

214     public final int getMaxLocals() {
215         return max_locals;
216     }
217
218
219     /**
220      * @return Maximum size of stack used by this method.
221      */

222     public final int getMaxStack() {
223         return max_stack;
224     }
225
226
227     /**
228      * @return the internal length of this code attribute (minus the first 6 bytes)
229      * and excluding all its attributes
230      */

231     private final int getInternalLength() {
232         return 2 /*max_stack*/+ 2 /*max_locals*/+ 4 /*code length*/
233                 + code_length /*byte-code*/
234                 + 2 /*exception-table length*/
235                 + 8 * exception_table_length /* exception table */
236                 + 2 /* attributes count */;
237     }
238
239
240     /**
241      * @return the full size of this code attribute, minus its first 6 bytes,
242      * including the size of all its contained attributes
243      */

244     private final int calculateLength() {
245         int len = 0;
246         for (int i = 0; i < attributes_count; i++) {
247             len += attributes[i].length + 6 /*attribute header size*/;
248         }
249         return len + getInternalLength();
250     }
251
252
253     /**
254      * @param attributes the attributes to set for this Code
255      */

256     public final void setAttributes( Attribute[] attributes ) {
257         this.attributes = attributes;
258         attributes_count = (attributes == null) ? 0 : attributes.length;
259         length = calculateLength(); // Adjust length
260
}
261
262
263     /**
264      * @param code byte code
265      */

266     public final void setCode( byte[] code ) {
267         this.code = code;
268         code_length = (code == null) ? 0 : code.length;
269     }
270
271
272     /**
273      * @param exception_table exception table
274      */

275     public final void setExceptionTable( CodeException[] exception_table ) {
276         this.exception_table = exception_table;
277         exception_table_length = (exception_table == null) ? 0 : exception_table.length;
278     }
279
280
281     /**
282      * @param max_locals maximum number of local variables
283      */

284     public final void setMaxLocals( int max_locals ) {
285         this.max_locals = max_locals;
286     }
287
288
289     /**
290      * @param max_stack maximum stack size
291      */

292     public final void setMaxStack( int max_stack ) {
293         this.max_stack = max_stack;
294     }
295
296
297     /**
298      * @return String representation of code chunk.
299      */

300     public final String JavaDoc toString( boolean verbose ) {
301         StringBuffer JavaDoc buf;
302         buf = new StringBuffer JavaDoc(100);
303         buf.append("Code(max_stack = ").append(max_stack).append(", max_locals = ").append(
304                 max_locals).append(", code_length = ").append(code_length).append(")\n").append(
305                 Utility.codeToString(code, constant_pool, 0, -1, verbose));
306         if (exception_table_length > 0) {
307             buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
308             for (int i = 0; i < exception_table_length; i++) {
309                 buf.append(exception_table[i].toString(constant_pool, verbose)).append("\n");
310             }
311         }
312         if (attributes_count > 0) {
313             buf.append("\nAttribute(s) = \n");
314             for (int i = 0; i < attributes_count; i++) {
315                 buf.append(attributes[i].toString()).append("\n");
316             }
317         }
318         return buf.toString();
319     }
320
321
322     /**
323      * @return String representation of code chunk.
324      */

325     public final String JavaDoc toString() {
326         return toString(true);
327     }
328
329
330     /**
331      * @return deep copy of this attribute
332      *
333      * @param _constant_pool the constant pool to duplicate
334      */

335     public Attribute copy( ConstantPool _constant_pool ) {
336         Code c = (Code) clone();
337         if (code != null) {
338             c.code = new byte[code.length];
339             System.arraycopy(code, 0, c.code, 0, code.length);
340         }
341         c.constant_pool = _constant_pool;
342         c.exception_table = new CodeException[exception_table_length];
343         for (int i = 0; i < exception_table_length; i++) {
344             c.exception_table[i] = exception_table[i].copy();
345         }
346         c.attributes = new Attribute[attributes_count];
347         for (int i = 0; i < attributes_count; i++) {
348             c.attributes[i] = attributes[i].copy(_constant_pool);
349         }
350         return c;
351     }
352 }
353
Popular Tags