1 2 package sli.kim.classfile; 3 4 import java.io.*; 5 6 11 public class ClassFileReader implements AccessFlags { 12 20 public void read(InputStream in, ClassInfo classInfo) 21 throws ClassFileParseException, IOException 22 { 23 readClass(new DataInputStream(new BufferedInputStream(in)), classInfo); 24 } 25 26 private void readClass(DataInput in, ClassInfo classInfo) 27 throws ClassFileParseException, IOException 28 { 29 short count; 30 31 { 33 int magic = in.readInt(); 34 if (magic != 0xCAFEBABE) 35 throw new ClassFileParseException("Invalid classfile magic number" + 36 ": expected 0xCAFEBABE, found 0x" + Integer.toHexString(magic)); 37 short major = in.readShort(), minor = in.readShort(); 38 if (major != 0x003) 40 throw new ClassFileParseException("Unrecognized classfile version " + 41 major + "." + minor); 42 } 43 44 ConstPool cp = new ConstPool(); 46 cp.read(in); 47 classInfo.setConstPool(cp); 48 49 { 51 short flags = in.readShort(); 52 short classIndex = in.readShort(); 53 short superClassIndex = in.readShort(); 54 short classNameIndex = cp.getEntryAtIndex(classIndex).getClassNameIndex(); 55 short superClassNameIndex = cp.getEntryAtIndex(superClassIndex).getClassNameIndex(); 56 String className = cp.getEntryAtIndex(classNameIndex).getString(); 57 String superClassName = cp.getEntryAtIndex(superClassNameIndex).getString(); 58 59 if (Debug.readClass != null) Debug.println(Debug.readClass, 60 "flags=" + flags + 61 "; class index=" + classIndex + 62 "; super class index=" + superClassIndex); 63 64 classInfo.setAccessFlags(flags); 65 classInfo.setName(className); 66 classInfo.setSuperClassName(superClassName); 67 } 68 69 count = in.readShort(); 71 if (Debug.readClass != null) Debug.println(Debug.readClass, 72 "#interfaces=" + count); 73 Debug.indent(); 74 for (int i = 0; i < count; i++) 75 classInfo.addInterface(readInterface(cp, in)); 76 Debug.outdent(); 77 78 count = in.readShort(); 80 if (Debug.readClass != null) Debug.println(Debug.readClass, 81 "#fields=" + count); 82 Debug.indent(); 83 for (int i = 0; i < count; i++) 84 classInfo.addField(readField(cp, in)); 85 Debug.outdent(); 86 87 count = in.readShort(); 89 if (Debug.readClass != null) Debug.println(Debug.readClass, 90 "#methods=" + count); 91 Debug.indent(); 92 for (int i = 0; i < count; i++) 93 classInfo.addMethod(readMethod(cp, in)); 94 Debug.outdent(); 95 96 count = in.readShort(); 98 if (Debug.readClass != null) Debug.println(Debug.readClass, 99 "#attributes=" + count); 100 Debug.indent(); 101 for (int i = 0; i < count; i++) 102 readClassAttribute(classInfo, cp, in); 103 Debug.outdent(); 104 } 105 106 private String readInterface(ConstPool cp, DataInput in) 107 throws IOException 108 { 109 short classIndex = in.readShort(); 110 if (Debug.readInterface != null) Debug.println(Debug.readInterface, 111 "class index=" + classIndex); 112 short nameIndex = cp.getEntryAtIndex(classIndex).getClassNameIndex(); 113 return cp.getEntryAtIndex(nameIndex).getString(); 114 } 115 116 private FieldInfo readField(ConstPool cp, DataInput in) 117 throws ClassFileParseException, IOException 118 { 119 FieldInfo result; 120 121 { 123 short flags = in.readShort(); 124 short nameIndex = in.readShort(); 125 short signatureIndex = in.readShort(); 126 127 if (Debug.readField != null) Debug.println(Debug.readField, 128 "flags=" + flags + 129 "; name index=" + nameIndex + 130 "; signature index=" + signatureIndex); 131 132 result = new FieldInfo(flags, cp.getEntryAtIndex(nameIndex).getString(), 133 cp.getEntryAtIndex(signatureIndex).getString()); 134 } 135 136 short numAttributes = in.readShort(); 138 if (Debug.readField != null) Debug.println(Debug.readField, 139 "#attributes=" + numAttributes); 140 Debug.indent(); 141 for (int i = 0; i < numAttributes; i++) 142 readFieldAttribute(result, cp, in); 143 Debug.outdent(); 144 145 return result; 146 } 147 148 private MethodInfo readMethod(ConstPool cp, DataInput in) 149 throws ClassFileParseException, IOException 150 { 151 MethodInfo result; 152 153 { 155 short flags = in.readShort(); 156 short nameIndex = in.readShort(); 157 short signatureIndex = in.readShort(); 158 String methodName = cp.getEntryAtIndex(nameIndex).getString(); 159 String methodSignature = cp.getEntryAtIndex(signatureIndex).getString(); 160 161 if (Debug.readMethod != null) Debug.println(Debug.readMethod, 162 "flags=" + flags + 163 "; name index=" + nameIndex + 164 "; signature index=" + signatureIndex); 165 166 result = new MethodInfo(flags, methodName, methodSignature); 167 } 168 169 short methodAttrCount = in.readShort(); 171 if (Debug.readMethod != null) Debug.println(Debug.readMethod, 172 "#attributes=" + methodAttrCount); 173 Debug.indent(); 174 175 for (int iMethodAttr = 0; iMethodAttr < methodAttrCount; iMethodAttr++) 176 readMethodAttribute(result, cp, in); 177 178 Debug.outdent(); 179 180 return result; 181 } 182 183 private void readClassAttribute(ClassInfo classInfo, ConstPool cp, 184 DataInput in) throws IOException 185 { 186 short nameIndex = in.readShort(); 187 int length = in.readInt(); 188 189 byte[] bytes = new byte[length]; 192 in.readFully(bytes); 193 in = new DataInputStream(new ByteArrayInputStream(bytes)); 194 195 if (Debug.readClass != null) Debug.println(Debug.readClass, 196 "attribute name index=" + nameIndex + 197 "; length=" + length); 198 Debug.indent(); 199 200 try { 201 202 String name = cp.getEntryAtIndex(nameIndex).getString(); 203 204 if (name.equals("SourceFile")) { 206 short filenameIndex = in.readShort(); 207 if (Debug.readClass != null) Debug.println(Debug.readClass, 208 "filename index=" + filenameIndex); 209 classInfo.setSourceFile(cp.getEntryAtIndex(filenameIndex).getString()); 210 } 211 212 else if (name.equals("InnerClasses")) 213 classInfo.setInnerClasses(readInnerClasses(cp, in)); 214 215 else 216 classInfo.addAttribute(readUnknownAttribute(name, length, in)); 217 218 } catch (ConstPoolEntryError e) { 219 if (Debug.readBadData != null) Debug.println(Debug.readBadData, 220 "class attribute name index=" + nameIndex); 221 } 222 223 Debug.outdent(); 224 } 225 226 private void readFieldAttribute(FieldInfo fieldInfo, ConstPool cp, 227 DataInput in) throws IOException 228 { 229 short nameIndex = in.readShort(); 230 String name = cp.getEntryAtIndex(nameIndex).getString(); 231 int length = in.readInt(); 232 233 byte[] bytes = new byte[length]; 236 in.readFully(bytes); 237 in = new DataInputStream(new ByteArrayInputStream(bytes)); 238 239 if (Debug.readField != null) Debug.println(Debug.readField, 240 "attribute name index=" + nameIndex + 241 "; length=" + length); 242 Debug.indent(); 243 244 try { 245 246 if (name.equals("ConstantValue")) { 248 short cvIndex = in.readShort(); 249 if (Debug.readField != null) Debug.println(Debug.readField, 250 "constant value index=" + cvIndex); 251 fieldInfo.setConstantValue(cp.getEntryAtIndex(cvIndex).getPrimitiveTypeValue()); 252 } 253 254 else if (name.equals("Synthetic")) { 255 if (Debug.readField != null) Debug.println(Debug.readField, 256 "synthetic"); 257 fieldInfo.setSynthetic(true); 258 } 259 260 else 261 fieldInfo.addAttribute(readUnknownAttribute(name, length, in)); 262 263 } catch (ConstPoolEntryError e) { 264 if (Debug.readBadData != null) Debug.println(Debug.readBadData, 265 "field attribute name index=" + nameIndex); 266 } 267 268 Debug.outdent(); 269 } 270 271 private void readMethodAttribute(MethodInfo methodInfo, ConstPool cp, 272 DataInput in) throws IOException 273 { 274 short nameIndex = in.readShort(); 275 int length = in.readInt(); 276 277 byte[] bytes = new byte[length]; 280 in.readFully(bytes); 281 in = new DataInputStream(new ByteArrayInputStream(bytes)); 282 283 if (Debug.readMethod != null) Debug.println(Debug.readMethod, 284 "attribute name index=" + nameIndex + 285 "; length=" + length); 286 Debug.indent(); 287 288 try { 289 290 String name = cp.getEntryAtIndex(nameIndex).getString(); 291 if (name.equals("Exceptions")) { 292 int count = in.readShort(); 293 for (int i = 0; i < count; i++) { 294 short exceptionClassIndex = in.readShort(); 295 short exceptionClassNameIndex = cp.getEntryAtIndex(exceptionClassIndex).getClassNameIndex(); 296 String exceptionName = cp.getEntryAtIndex(exceptionClassNameIndex). getString(); 297 methodInfo.addException(exceptionName); 298 } 299 } 300 301 else if (name.equals("Code")) 302 methodInfo.setCodeInfo(readCode(cp, in)); 303 304 else if (name.equals("Deprecated")) { 305 if (Debug.readMethod != null) Debug.println(Debug.readMethod, 306 "deprecated"); 307 methodInfo.setDeprecated(true); 308 } 309 310 else 311 methodInfo.addAttribute(readUnknownAttribute(name, length, in)); 312 313 } catch (ConstPoolEntryError e) { 314 if (Debug.readBadData != null) Debug.println(Debug.readBadData, 315 "method attribute name index=" + nameIndex); 316 } 317 318 Debug.outdent(); 319 } 320 321 private CodeInfo readCode(ConstPool cp, DataInput in) 322 throws IOException 323 { 324 short maxStack = in.readShort(); 326 short maxLocals = in.readShort(); 327 byte[] bytecode = new byte[in.readInt()]; 328 329 if (Debug.readCode != null) Debug.println(Debug.readCode, 330 "maxStack=" + maxStack + 331 "; maxLocals=" + maxLocals + 332 "; bytecode length=" + bytecode.length); 333 334 in.readFully(bytecode); 335 336 ExceptionInfo[] exceptionTable = new ExceptionInfo[in.readShort()]; 338 if (Debug.readCode != null) Debug.println(Debug.readCode, 339 "exception table length=" + exceptionTable.length); 340 Debug.indent(); 341 for (int i = 0; i < exceptionTable.length; i++) { 342 short startPC = in.readShort(); 343 short endPC = in.readShort(); 344 short handlerPC = in.readShort(); 345 short catchTypeIndex = in.readShort(); 346 347 if (Debug.readCode != null) Debug.println(Debug.readCode, 348 "startPC=" + startPC + 349 "; endPC=" + endPC + 350 "; handlerPC=" + handlerPC + 351 "; catchTypeIndex=" + catchTypeIndex); 352 353 String catchType = null; 354 if (catchTypeIndex != 0) { short catchTypeNameIndex = 356 cp.getEntryAtIndex(catchTypeIndex).getClassNameIndex(); 357 catchType = cp.getEntryAtIndex(catchTypeNameIndex).getString(); 358 } 359 exceptionTable[i] = 360 new ExceptionInfo(startPC, endPC, handlerPC, catchType); 361 } 362 Debug.outdent(); 363 364 CodeInfo codeInfo = 365 new CodeInfo(maxStack, maxLocals, bytecode, exceptionTable); 366 367 short codeAttrCount = in.readShort(); 369 if (Debug.readCode != null) Debug.println(Debug.readCode, 370 "#attributes=" + codeAttrCount); 371 Debug.indent(); 372 for (int iCodeAttr = 0; iCodeAttr < codeAttrCount; iCodeAttr++) 373 readCodeAttribute(codeInfo, cp, in); 374 Debug.outdent(); 375 376 return codeInfo; 377 } 378 379 private void readCodeAttribute(CodeInfo codeInfo, ConstPool cp, 380 DataInput in) throws IOException 381 { 382 short nameIndex = in.readShort(); 383 int length = in.readInt(); 384 385 byte[] bytes = new byte[length]; 388 in.readFully(bytes); 389 in = new DataInputStream(new ByteArrayInputStream(bytes)); 390 391 if (Debug.readCode != null) Debug.println(Debug.readCode, 392 "code attribute name index=" + nameIndex + 393 "; length=" + length); 394 Debug.indent(); 395 396 try { 397 398 String name = cp.getEntryAtIndex(nameIndex).getString(); 399 if (name.equals("LineNumberTable")) 400 codeInfo.setLineNumberTable(readLineNumberTable(in)); 401 else if (name.equals("LocalVariableTable")) 402 codeInfo.setLocalVariableTable(readLocalVariableTable(cp, in)); 403 else 404 codeInfo.addAttribute(readUnknownAttribute(name, length, in)); 405 406 } catch (ConstPoolEntryError e) { 407 if (Debug.readBadData != null) Debug.println(Debug.readBadData, 408 "code attribute name index=" + nameIndex); 409 } 410 411 Debug.outdent(); 412 } 413 414 private InnerClassInfo[] readInnerClasses(ConstPool cp, DataInput in) 415 throws IOException 416 { 417 short rows = in.readShort(); 418 if (Debug.readInnerClasses != null) Debug.println(Debug.readInnerClasses, 419 "#inner classes=" + rows); 420 InnerClassInfo[] classes = new InnerClassInfo[rows]; 421 for (int i = 0; i < rows; i++) { 422 short innerClassIndex = in.readShort(); 423 short outerClassIndex = in.readShort(); 424 short simpleNameIndex = in.readShort(); 425 short flags = in.readShort(); 426 427 if (Debug.readInnerClasses != null) Debug.println(Debug.readInnerClasses, 428 "inner class index=" + innerClassIndex + 429 "; outer class index=" + outerClassIndex + 430 "; simple name index=" + simpleNameIndex + 431 "; flags=" + flags); 432 433 short innerClassNameIndex = cp.getEntryAtIndex(innerClassIndex).getClassNameIndex(); 434 String innerClassName = cp.getEntryAtIndex(innerClassNameIndex).getString(); 435 String outerClassName = null; 436 if (outerClassIndex != 0) { 437 short outerClassNameIndex = cp.getEntryAtIndex(outerClassIndex).getClassNameIndex(); 438 outerClassName = cp.getEntryAtIndex(outerClassNameIndex).getString(); 439 } 440 String simpleName = null; 441 if (simpleNameIndex != 0) 442 simpleName = cp.getEntryAtIndex(simpleNameIndex).getString(); 443 444 classes[i] = new InnerClassInfo(innerClassName, outerClassName, simpleName, flags); 445 } 446 return classes; 447 } 448 449 private LocalVariableInfo[] readLocalVariableTable(ConstPool cp, DataInput in) 450 throws IOException 451 { 452 LocalVariableInfo[] table = new LocalVariableInfo[in.readShort()]; 453 if (Debug.readLocalVariables != null) Debug.println(Debug.readLocalVariables, 454 "#local variables=" + table.length); 455 for (int i = 0; i < table.length; i++) { 456 short startPC = in.readShort(); 457 short length = in.readShort(); 458 short nameIndex = in.readShort(); 459 short signatureIndex = in.readShort(); 460 short slot= in.readShort(); 461 if (Debug.readLocalVariables != null) Debug.println(Debug.readLocalVariables, 462 "start PC=" + startPC + 463 "; length=" + length + 464 "; name index=" + nameIndex + 465 "; signature index=" + signatureIndex + 466 "; slot=" + slot); 467 468 String name = cp.getEntryAtIndex(nameIndex).getString(); 469 String signature = cp.getEntryAtIndex(signatureIndex).getString(); 470 table[i] = new LocalVariableInfo(startPC, length, name, signature, slot); 471 } 472 return table; 473 } 474 475 private LineNumberInfo[] readLineNumberTable(DataInput in) 476 throws IOException 477 { 478 LineNumberInfo[] table = new LineNumberInfo[in.readShort()]; 479 if (Debug.readLineNumbers != null) Debug.println(Debug.readLineNumbers, 480 "#line numbers=" + table.length); 481 for (int i = 0; i < table.length; i++) { 482 short startPC = in.readShort(); 483 short lineNumber = in.readShort(); 484 485 if (Debug.readLineNumbers != null) Debug.println(Debug.readLineNumbers, 486 "start PC=" + startPC + 487 "; line number=" + lineNumber); 488 489 table[i] = new LineNumberInfo(startPC, lineNumber); 490 } 491 return table; 492 } 493 494 private AttributeInfo readUnknownAttribute(String name, int length, DataInput in) 495 throws IOException 496 { 497 if (Debug.readUnknownAttribute != null) Debug.println(Debug.readUnknownAttribute, 498 "attribute name=\"" + name + "\""); 499 byte[] data = new byte[length]; 500 in.readFully(data); 501 return new AttributeInfo(name, data); 502 } 503 } 504 | Popular Tags |