KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > classfile > CodeAttribute


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.classfile;
26
27 import java.util.Vector JavaDoc;
28 import java.io.*;
29
30 /**
31  * Subtype of ClassAttribute which describes the "Code" attribute
32  * associated with a method.
33  */

34
35 public class CodeAttribute extends ClassAttribute {
36     public final static String JavaDoc expectedAttrName = "Code";//NOI18N
37

38   /* The java class file contents defining this code attribute.
39      If non-null, this must be disassembled before the remaining
40      fields of this instance may be accessed. */

41   private byte theDataBytes[];
42
43   /* The maximum number of stack entries used by this method */
44   private int maxStack;
45
46   /* The maximum number of local variables used by this method */
47   private int maxLocals;
48
49   /* The java VM byte code sequence for this method - null for native
50      and abstract methods */

51   private byte theCodeBytes[];
52
53   /* The instruction sequence for this method - initially derived from
54      the byte code array, but may later be modified */

55   private Insn theCode;
56
57   /* The exception ranges and handlers which apply to the code in this
58      method */

59   private ExceptionTable exceptionTable;
60
61   /* The attributes which apply to this method */
62   private AttributeVector codeAttributes;
63
64   /* The method environment used for decompiling this code attribute */
65   CodeEnv codeEnv;
66
67   /* public accessors */
68
69
70   /**
71    * Return the maximum number of stack entries used by this method
72    */

73   public int stackUsed() {
74     makeValid();
75     return maxStack;
76   }
77
78   /**
79    * Set the maximum number of stack entries used by this method
80    */

81   public void setStackUsed(int used) {
82     makeValid();
83     maxStack = used;
84   }
85
86   /**
87    * Return the maximum number of local variables used by this method
88    */

89   public int localsUsed() {
90     makeValid();
91     return maxLocals;
92   }
93
94   /**
95    * Set the maximum number of local variables used by this method
96    */

97   public void setLocalsUsed(int used) {
98     makeValid();
99     maxLocals = used;
100   }
101
102   /**
103    * Return the java VM byte code sequence for this method - null for
104    * native and abstract methods
105    */

106   public byte[] byteCodes() {
107     makeValid();
108     return theCodeBytes;
109   }
110
111   /**
112    * Return the instruction sequence for this method - initially derived
113    * from the byte code array, but may later be modified
114    */

115   public Insn theCode() {
116     makeValid();
117     if (theCode == null && codeEnv != null) {
118       buildInstructions(codeEnv);
119     }
120     return theCode;
121   }
122
123   /**
124    * Install the instruction sequence for this method - the byte code array
125    * is later updated.
126    */

127   public void setTheCode(Insn insn) {
128     makeValid();
129     if (insn != null && insn.opcode() != Insn.opc_target)
130       throw new InsnError(
131           "The initial instruction in all methods must be a target");//NOI18N
132
theCode = insn;
133   }
134
135   /**
136    * Return the exception ranges and handlers which apply to the code in
137    * this method.
138    */

139   public ExceptionTable exceptionHandlers() {
140     makeValid();
141     return exceptionTable;
142   }
143
144   /**
145    * Return the attributes which apply to this code
146    */

147   public AttributeVector attributes() {
148     makeValid();
149     return codeAttributes;
150   }
151
152
153   /**
154    * Constructs a CodeAttribute object for construction from scratch
155    */

156   public CodeAttribute(ConstUtf8 attrName,
157                int maxStack, int maxLocals,
158                Insn code,
159                ExceptionTable excTable,
160                AttributeVector codeAttrs) {
161     this(attrName, maxStack, maxLocals, code, null, /* byteCodes */
162      excTable, codeAttrs, null /* CodeEnv */ );
163   }
164
165   /**
166    * Constructs a CodeAttribute object
167    */

168   public CodeAttribute(ConstUtf8 attrName,
169                int maxStack, int maxLocals,
170                Insn code, byte[] codeBytes,
171                ExceptionTable excTable,
172                AttributeVector codeAttrs,
173                CodeEnv codeEnv) {
174     super(attrName);
175     this.maxStack = maxStack;
176     this.maxLocals = maxLocals;
177     theCode = code;
178     theCodeBytes = codeBytes;
179     exceptionTable = excTable;
180     codeAttributes = codeAttrs;
181     this.codeEnv = codeEnv;
182   }
183
184
185   /**
186    * Constructs a CodeAttribute object for later disassembly
187    */

188   public CodeAttribute(ConstUtf8 attrName, byte[] dataBytes, CodeEnv codeEnv) {
189     super(attrName);
190     this.theDataBytes = dataBytes;
191     this.codeEnv = codeEnv;
192   }
193
194
195   /* package local methods */
196
197
198   static CodeAttribute read(ConstUtf8 attrName,
199                 DataInputStream data, ConstantPool pool)
200     throws IOException {
201     int maxStack = data.readUnsignedShort();
202     int maxLocals = data.readUnsignedShort();
203     int codeLength = data.readInt();
204     byte codeBytes[] = new byte[codeLength];
205     data.readFully(codeBytes);
206     Insn code = null;
207     CodeEnv codeEnv = new CodeEnv(pool);
208
209     ExceptionTable excTable = ExceptionTable.read(data, codeEnv);
210     
211     AttributeVector codeAttrs =
212       AttributeVector.readAttributes(data, codeEnv);
213
214     return new CodeAttribute(attrName, maxStack, maxLocals, code, codeBytes,
215                  excTable, codeAttrs, codeEnv);
216   }
217
218   /* This version reads the attribute into a byte array for later
219      consumption */

220   static CodeAttribute read(ConstUtf8 attrName, int attrLength,
221                 DataInputStream data, ConstantPool pool)
222     throws IOException {
223     byte dataBytes[] = new byte[attrLength];
224     data.readFully(dataBytes);
225     return new CodeAttribute(attrName, dataBytes, new CodeEnv(pool));
226   }
227
228   void write(DataOutputStream out) throws IOException {
229     out.writeShort(attrName().getIndex());
230     if (theDataBytes == null) {
231       buildInstructionBytes();
232       ByteArrayOutputStream baos = new ByteArrayOutputStream();
233       DataOutputStream tmpOut = new DataOutputStream(baos);
234       tmpOut.writeShort(maxStack);
235       tmpOut.writeShort(maxLocals);
236       tmpOut.writeInt(theCodeBytes.length);
237       tmpOut.write(theCodeBytes, 0, theCodeBytes.length);
238       exceptionTable.write(tmpOut);
239       codeAttributes.write(tmpOut);
240
241       tmpOut.flush();
242       byte tmpBytes[] = baos.toByteArray();
243       out.writeInt(tmpBytes.length);
244       out.write(tmpBytes, 0, tmpBytes.length);
245     } else {
246       out.writeInt(theDataBytes.length);
247       out.write(theDataBytes, 0, theDataBytes.length);
248     }
249   }
250
251   void print(PrintStream out, int indent) {
252     makeValid();
253     ClassPrint.spaces(out, indent);
254     out.print("Code:");//NOI18N
255
out.print(" max_stack = " + Integer.toString(maxStack));//NOI18N
256
out.print(" max_locals = " + Integer.toString(maxLocals));//NOI18N
257
out.println(" Exceptions:");//NOI18N
258
exceptionTable.print(out, indent+2);
259     ClassPrint.spaces(out, indent);
260     out.println("Code Attributes:");//NOI18N
261
codeAttributes.print(out, indent+2);
262
263     Insn insn = theCode();
264     if (insn != null) {
265       ClassPrint.spaces(out, indent);
266       out.println("Instructions:");//NOI18N
267
while (insn != null) {
268     insn.print(out, indent+2);
269     insn = insn.next();
270       }
271     }
272   }
273
274   /**
275    * Assign offsets to instructions and return the number of bytes.
276    * theCode must be non-null.
277    */

278   private int resolveOffsets() {
279     Insn insn = theCode;
280     int currPC = 0;
281     while (insn != null) {
282       currPC = insn.resolveOffset(currPC);
283       insn = insn.next();
284     }
285     return currPC;
286   }
287
288   int codeSize() {
289     makeValid();
290     return theCodeBytes.length;
291   }
292
293   /**
294    * Derive the instruction list from the instruction byte codes
295    */

296   private void buildInstructions(CodeEnv codeEnv) {
297     if (theCodeBytes != null) {
298       InsnReadEnv insnEnv = new InsnReadEnv(theCodeBytes, codeEnv);
299       theCode = insnEnv.getTarget(0);
300       Insn currInsn = theCode;
301
302       /* First, create instructions */
303       while (insnEnv.more()) {
304     Insn newInsn = Insn.read(insnEnv);
305     currInsn.setNext(newInsn);
306     currInsn = newInsn;
307       }
308
309       /* Now, insert targets */
310       InsnTarget targ;
311       currInsn = theCode;
312       Insn prevInsn = null;
313       while (currInsn != null) {
314     int off = currInsn.offset();
315
316     /* We always insert a target a 0 to start so ignore that one */
317     if (off > 0) {
318       targ = codeEnv.findTarget(off);
319       if (targ != null)
320         prevInsn.setNext(targ);
321     }
322     prevInsn = currInsn;
323     currInsn = currInsn.next();
324       }
325
326       /* And follow up with a final target if needed */
327       targ = codeEnv.findTarget(insnEnv.currentPC());
328       if (targ != null)
329     prevInsn.setNext(targ);
330     }
331   }
332
333   /**
334    * Derive the instruction byte codes from the instruction list
335    * This should also recompute stack and variables but for now we
336    * assume that this isn't needed
337    */

338   private void buildInstructionBytes() {
339     if (theCode != null) {
340       /* Make sure instructions have correct offsets */
341       int size = resolveOffsets();
342       theCodeBytes = new byte[size];
343
344       Insn insn = theCode;
345       int index = 0;
346       while (insn != null) {
347     index = insn.store(theCodeBytes, index);
348     insn = insn.next();
349       }
350     }
351   }
352
353   /** If theDataBytes is non-null, disassemble this code attribute
354    * from the data bytes. */

355   private void makeValid() {
356     if (theDataBytes != null) {
357       DataInputStream dis = new DataInputStream(
358         new ByteArrayInputStream(theDataBytes));
359       try {
360     maxStack = dis.readUnsignedShort();
361     maxLocals = dis.readUnsignedShort();
362     int codeLength = dis.readInt();
363     theCodeBytes = new byte[codeLength];
364     dis.readFully(theCodeBytes);
365     exceptionTable = ExceptionTable.read(dis, codeEnv);
366     codeAttributes = AttributeVector.readAttributes(dis, codeEnv);
367       } catch (java.io.IOException JavaDoc ioe) {
368           ClassFormatError JavaDoc cfe = new ClassFormatError JavaDoc(
369         "IOException while reading code attribute");//NOI18N
370
cfe.initCause(ioe);
371           throw cfe;
372       }
373
374       theDataBytes = null;
375     }
376   }
377
378 }
379
380
Popular Tags