1 2 /** 3 4 The author of this software is Ian Kaplan 5 Bear Products International 6 www.bearcave.com 7 iank@bearcave.com 8 9 Copyright (c) Ian Kaplan, 1999, 2000 10 11 See copyright file for usage and licensing 12 13 */ 14 15 package attr; 16 17 import java.util.Vector; 18 import java.io.*; 19 import util.*; 20 import jconst.*; 21 22 23 /** 24 25 Attribute for the byte code for a Java method. The attribute name 26 for the codeAttr is "Code". Note that if the method is native or 27 abstract, then it can't have a "Code" attribute. 28 29 <p> 30 The structure of a Code attribute is: 31 32 <pre> 33 Code_attribute { 34 u2 name_index; 35 u4 total_length; 36 u2 max_stack; 37 u2 max_locals; 38 u4 code_length; 39 u1 code[ code_length ]; 40 u2 exceptions_table_length; 41 exceptInfo except[ exceptions_table_length ]; 42 u2 attributes_count; 43 attribute_info attributes[ attributes_count ]; 44 } 45 </pre> 46 47 <p> 48 49 Where 50 51 <pre> 52 exceptInfo { 53 u2 start_pc; 54 U2 end_pc; 55 u2 handler_pc; 56 u2 catch_type; 57 } 58 </pre> 59 60 <p> 61 The attribute_name_index and attribute length are read by the 62 attrFactory.allocAttr method. These values are passed into the class 63 constructor. 64 65 <p> 66 In the exceptInfo the catch_type is an index into the constant 67 pool. The object at this index must be a CONSTANT_Class_info 68 object (e.g., constClass_or_String) for an exception class that 69 this exception is designated to catch. This class must be the 70 class Throwable or one of its subclasses. 71 <p> 72 Although code_length is 32-bits wide, its value must be less than 73 0x10000 (65536) (see JVM Spec 4.8.1). 74 <p> 75 The max_stack value is the size of the operand stack. This in 76 in word units, where an int is one word and a long or double 77 is two: 78 79 At any point in time an operand stack has an associated depth, 80 where a value of type long or double contributes two units to 81 the depth and a value of any other type contributes one unit. 82 (JVM Spec 3.6.2) 83 84 The max_locals value is the size of the local frame allocated on 85 entry to the method. This frame will hold local variables and 86 method arguments. As with max_stack, the units are words. Like 87 the stack, the frame is word aligned so a boolean or a byte 88 occupies a word and a long or a double occupies two words (JVM 89 Spec 3.6.1). 90 91 If max_locals is zero, then there are no local variables. 92 93 If debug is turned and the method has local variables then 94 the codeAttributes table will contain a LocalVariableTable 95 attribute. This attribute in turn contains a table of 96 local variable information. 97 98 @author Ian Kaplan 99 100 */ 101 public class codeAttr extends attrInfo { 102 private int max_stack; 103 private int max_locals; 104 private byte codeBuf[]; 105 private exceptInfo exceptTab[] = null; 106 private attrInfo codeAttributes[] = null; 107 108 109 // 110 // exceptInfo 111 // 112 // Exception information 113 // 114 class exceptInfo { 115 int startPC; 116 int endPC; 117 int handlerPC; 118 constClass_or_String catch_type = null; 119 120 exceptInfo( DataInputStream dStream, constPool constPoolSec ) { 121 startPC = readU2( dStream ); 122 endPC = readU2( dStream ); 123 handlerPC = readU2( dStream ); 124 int catchTypeIx = readU2( dStream ); 125 126 if (catchTypeIx > 0) { 127 constBase obj = constPoolSec.constPoolElem( catchTypeIx ); 128 if (obj != null && obj instanceof constClass_or_String) { 129 catch_type = (constClass_or_String)obj; 130 } 131 else { 132 errorMessage.errorPrint("exceptInfo: constClass_or_String expected in const pool index " + catchTypeIx ); 133 } 134 } 135 } // exceptInfo constructor 136 137 } // exceptInfo (inner class) 138 139 140 /** 141 codeAttr constructor 142 143 <p> 144 145 Here the length argument is the attribute length (e.g., the 146 total length of the attribute). 147 148 */ 149 public codeAttr( String name, int length, 150 DataInputStream dStream, constPool constPoolSec ) { 151 super( name, length ); // invoke the attrInfo constructor 152 153 max_stack = readU2( dStream ); 154 max_locals = readU2( dStream ); 155 int codeLen = readU4( dStream ); 156 157 if (codeLen > 0) { 158 codeBuf = new byte[ codeLen ]; 159 160 // 161 // Read the code into the code buffer. The code is 162 // read byte by byte. Since buffered input (e.g., the 163 // DataInputStream object) is used this should not be 164 // a performace issue. 165 // 166 for (int i = 0; i < codeBuf.length; i++) { 167 codeBuf[i] = (byte)readU1( dStream ); 168 } // for 169 } 170 171 int exceptLen = readU2( dStream ); 172 173 if (exceptLen > 0) { 174 exceptTab = new exceptInfo[ exceptLen ]; 175 176 for (int i = 0; i < exceptLen; i++) { 177 exceptTab[i] = new exceptInfo( dStream, constPoolSec ); 178 } 179 } 180 181 int attrCount = readU2( dStream ); 182 183 if (attrCount > 0) { 184 codeAttributes = new attrInfo[ attrCount ]; 185 186 for (int i = 0; i < attrCount; i++) { 187 codeAttributes[i] = attrFactory.allocAttr( dStream, constPoolSec ); 188 } // for 189 } 190 } // codeAttr constructor 191 192 /** 193 If there are local variables in the method, return a vector 194 containing the local variable name declarations. There should 195 be only one localVarTabAttr in the codeAttributes table. 196 */ 197 public Vector getLocalVarVec() { 198 Vector varVec = null; 199 200 if (codeAttributes != null) { 201 for (int i = 0; i < codeAttributes.length; i++) { 202 if (codeAttributes[i] instanceof localVarTabAttr) { 203 varVec = ((localVarTabAttr)codeAttributes[i]).getLocalVarVec(); 204 break; 205 } 206 } // for 207 208 } // if 209 210 return varVec; 211 } // getLocalVarVec 212 213 214 public int getMax_locals() { return max_locals; } 215 public int getMax_stack() { return max_stack; } 216 217 } // codeAttr 218