1 package org.apache.bcel.classfile;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache BCEL" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache BCEL", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import org.apache.bcel.Constants;
58 import java.io.*;
59
60 /***
61 * This class represents a chunk of Java byte code contained in a
62 * method. It is instantiated by the
63 * <em>Attribute.readAttribute()</em> method. A <em>Code</em>
64 * attribute contains informations about operand stack, local
65 * variables, byte code and the exceptions handled within this
66 * method.
67 *
68 * This attribute has attributes itself, namely <em>LineNumberTable</em> which
69 * is used for debugging purposes and <em>LocalVariableTable</em> which
70 * contains information about the local variables.
71 *
72 * @version $Id: Code.java,v 1.2 2002/03/11 16:16:35 mdahm Exp $
73 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
74 * @see Attribute
75 * @see CodeException
76 * @see LineNumberTable
77 * @see LocalVariableTable
78 */
79 public final class Code extends Attribute {
80 private int max_stack; // Maximum size of stack used by this method
81 private int max_locals; // Number of local variables
82 private int code_length; // Length of code in bytes
83 private byte[] code; // Actual byte code
84
85 private int exception_table_length;
86 private CodeException[] exception_table; // Table of handled exceptions
87 private int attributes_count; // Attributes of code: LineNumber
88 private Attribute[] attributes; // or LocalVariable
89
90 /***
91 * Initialize from another object. Note that both objects use the same
92 * references (shallow copy). Use copy() for a physical copy.
93 */
94 public Code(Code c) {
95 this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(),
96 c.getCode(), c.getExceptionTable(), c.getAttributes(),
97 c.getConstantPool());
98 }
99
100 /***
101 * @param name_index Index pointing to the name <em>Code</em>
102 * @param length Content length in bytes
103 * @param file Input stream
104 * @param constant_pool Array of constants
105 */
106 Code(int name_index, int length, DataInputStream file,
107 ConstantPool constant_pool) throws IOException
108 {
109 // Initialize with some default values which will be overwritten later
110 this(name_index, length,
111 file.readUnsignedShort(), file.readUnsignedShort(),
112 (byte[])null, (CodeException[])null, (Attribute[])null,
113 constant_pool);
114
115 code_length = file.readInt();
116 code = new byte[code_length]; // Read byte code
117 file.readFully(code);
118
119 /* Read exception table that contains all regions where an exception
120 * handler is active, i.e., a try { ... } catch() block.
121 */
122 exception_table_length = file.readUnsignedShort();
123 exception_table = new CodeException[exception_table_length];
124
125 for(int i=0; i < exception_table_length; i++)
126 exception_table[i] = new CodeException(file);
127
128 /* Read all attributes, currently `LineNumberTable' and
129 * `LocalVariableTable'
130 */
131 attributes_count = file.readUnsignedShort();
132 attributes = new Attribute[attributes_count];
133 for(int i=0; i < attributes_count; i++)
134 attributes[i] = Attribute.readAttribute(file, constant_pool);
135
136 /* Adjust length, because of setAttributes in this(), s.b. length
137 * is incorrect, because it didn't take the internal attributes
138 * into account yet! Very subtle bug, fixed in 3.1.1.
139 */
140 this.length = length;
141 }
142
143 /***
144 * @param name_index Index pointing to the name <em>Code</em>
145 * @param length Content length in bytes
146 * @param max_stack Maximum size of stack
147 * @param max_locals Number of local variables
148 * @param code Actual byte code
149 * @param exception_table Table of handled exceptions
150 * @param attributes Attributes of code: LineNumber or LocalVariable
151 * @param constant_pool Array of constants
152 */
153 public Code(int name_index, int length,
154 int max_stack, int max_locals,
155 byte[] code,
156 CodeException[] exception_table,
157 Attribute[] attributes,
158 ConstantPool constant_pool)
159 {
160 super(Constants.ATTR_CODE, name_index, length, constant_pool);
161
162 this.max_stack = max_stack;
163 this.max_locals = max_locals;
164
165 setCode(code);
166 setExceptionTable(exception_table);
167 setAttributes(attributes); // Overwrites length!
168 }
169
170 /***
171 * Called by objects that are traversing the nodes of the tree implicitely
172 * defined by the contents of a Java class. I.e., the hierarchy of methods,
173 * fields, attributes, etc. spawns a tree of objects.
174 *
175 * @param v Visitor object
176 */
177 public void accept(Visitor v) {
178 v.visitCode(this);
179 }
180
181 /***
182 * Dump code attribute to file stream in binary format.
183 *
184 * @param file Output file stream
185 * @throws IOException
186 */
187 public final void dump(DataOutputStream file) throws IOException
188 {
189 super.dump(file);
190
191 file.writeShort(max_stack);
192 file.writeShort(max_locals);
193 file.writeInt(code_length);
194 file.write(code, 0, code_length);
195
196 file.writeShort(exception_table_length);
197 for(int i=0; i < exception_table_length; i++)
198 exception_table[i].dump(file);
199
200 file.writeShort(attributes_count);
201 for(int i=0; i < attributes_count; i++)
202 attributes[i].dump(file);
203 }
204
205 /***
206 * @return Collection of code attributes.
207 * @see Attribute
208 */
209 public final Attribute[] getAttributes() { return attributes; }
210
211 /***
212 * @return LineNumberTable of Code, if it has one
213 */
214 public LineNumberTable getLineNumberTable() {
215 for(int i=0; i < attributes_count; i++)
216 if(attributes[i] instanceof LineNumberTable)
217 return (LineNumberTable)attributes[i];
218
219 return null;
220 }
221
222 /***
223 * @return LocalVariableTable of Code, if it has one
224 */
225 public LocalVariableTable getLocalVariableTable() {
226 for(int i=0; i < attributes_count; i++)
227 if(attributes[i] instanceof LocalVariableTable)
228 return (LocalVariableTable)attributes[i];
229
230 return null;
231 }
232
233 /***
234 * @return Actual byte code of the method.
235 */
236 public final byte[] getCode() { return code; }
237
238 /***
239 * @return Table of handled exceptions.
240 * @see CodeException
241 */
242 public final CodeException[] getExceptionTable() { return exception_table; }
243
244 /***
245 * @return Number of local variables.
246 */
247 public final int getMaxLocals() { return max_locals; }
248
249 /***
250 * @return Maximum size of stack used by this method.
251 */
252
253 public final int getMaxStack() { return max_stack; }
254
255 /***
256 * @return the internal length of this code attribute (minus the first 6 bytes)
257 * and excluding all its attributes
258 */
259 private final int getInternalLength() {
260 return 2 /*max_stack*/ + 2 /*max_locals*/ + 4 /*code length*/
261 + code_length /*byte-code*/
262 + 2 /*exception-table length*/
263 + 8 * exception_table_length /* exception table */
264 + 2 /* attributes count */;
265 }
266
267 /***
268 * @return the full size of this code attribute, minus its first 6 bytes,
269 * including the size of all its contained attributes
270 */
271 private final int calculateLength() {
272 int len = 0;
273
274 for(int i=0; i < attributes_count; i++)
275 len += attributes[i].length + 6 /*attribute header size*/;
276
277 return len + getInternalLength();
278 }
279
280 /***
281 * @param attributes.
282 */
283 public final void setAttributes(Attribute[] attributes) {
284 this.attributes = attributes;
285 attributes_count = (attributes == null)? 0 : attributes.length;
286 length = calculateLength(); // Adjust length
287 }
288
289 /***
290 * @param code byte code
291 */
292 public final void setCode(byte[] code) {
293 this.code = code;
294 code_length = (code == null)? 0 : code.length;
295 }
296
297 /***
298 * @param exception_table exception table
299 */
300 public final void setExceptionTable(CodeException[] exception_table) {
301 this.exception_table = exception_table;
302 exception_table_length = (exception_table == null)? 0 :
303 exception_table.length;
304 }
305
306 /***
307 * @param max_locals maximum number of local variables
308 */
309 public final void setMaxLocals(int max_locals) {
310 this.max_locals = max_locals;
311 }
312
313 /***
314 * @param max_stack maximum stack size
315 */
316 public final void setMaxStack(int max_stack) {
317 this.max_stack = max_stack;
318 }
319
320 /***
321 * @return String representation of code chunk.
322 */
323 public final String toString(boolean verbose) {
324 StringBuffer buf;
325
326 buf = new StringBuffer("Code(max_stack = " + max_stack +
327 ", max_locals = " + max_locals +
328 ", code_length = " + code_length + ")\n" +
329 Utility.codeToString(code, constant_pool, 0, -1, verbose));
330
331 if(exception_table_length > 0) {
332 buf.append("\nException handler(s) = \n" + "From\tTo\tHandler\tType\n");
333
334 for(int i=0; i < exception_table_length; i++)
335 buf.append(exception_table[i].toString(constant_pool, verbose) + "\n");
336 }
337
338 if(attributes_count > 0) {
339 buf.append("\nAttribute(s) = \n");
340
341 for(int i=0; i < attributes_count; i++)
342 buf.append(attributes[i].toString() + "\n");
343 }
344
345 return buf.toString();
346 }
347
348 /***
349 * @return String representation of code chunk.
350 */
351 public final String toString() {
352 return toString(true);
353 }
354
355 /***
356 * @return deep copy of this attribute
357 */
358 public Attribute copy(ConstantPool constant_pool) {
359 Code c = (Code)clone();
360 c.code = (byte[])code.clone();
361 c.constant_pool = constant_pool;
362
363 c.exception_table = new CodeException[exception_table_length];
364 for(int i=0; i < exception_table_length; i++)
365 c.exception_table[i] = exception_table[i].copy();
366
367 c.attributes = new Attribute[attributes_count];
368 for(int i=0; i < attributes_count; i++)
369 c.attributes[i] = attributes[i].copy(constant_pool);
370
371 return c;
372 }
373 }
This page was automatically generated by Maven