1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.classfile.io; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.*; 25import proguard.classfile.attribute.annotation.*; 26import proguard.classfile.attribute.annotation.visitor.*; 27import proguard.classfile.attribute.preverification.*; 28import proguard.classfile.attribute.preverification.visitor.*; 29import proguard.classfile.attribute.visitor.*; 30import proguard.classfile.constant.*; 31import proguard.classfile.constant.visitor.ConstantVisitor; 32import proguard.classfile.util.*; 33import proguard.classfile.visitor.*; 34 35import java.io.DataInput; 36 37/** 38 * This ClassVisitor fills out the ProgramClass objects that it visits with data 39 * from the given DataInput object. 40 * 41 * @author Eric Lafortune 42 */ 43public class ProgramClassReader 44extends SimplifiedVisitor 45implements ClassVisitor, 46 MemberVisitor, 47 ConstantVisitor, 48 AttributeVisitor, 49 InnerClassesInfoVisitor, 50 ExceptionInfoVisitor, 51 StackMapFrameVisitor, 52 VerificationTypeVisitor, 53 LineNumberInfoVisitor, 54 LocalVariableInfoVisitor, 55 LocalVariableTypeInfoVisitor, 56 AnnotationVisitor, 57 ElementValueVisitor 58{ 59 private final RuntimeDataInput dataInput; 60 61 62 /** 63 * Creates a new ProgramClassReader for reading from the given DataInput. 64 */ 65 public ProgramClassReader(DataInput dataInput) 66 { 67 this.dataInput = new RuntimeDataInput(dataInput); 68 } 69 70 71 // Implementations for ClassVisitor. 72 73 public void visitProgramClass(ProgramClass programClass) 74 { 75 // Read and check the magic number. 76 programClass.u4magic = dataInput.readInt(); 77 78 ClassUtil.checkMagicNumber(programClass.u4magic); 79 80 // Read and check the version numbers. 81 int u2minorVersion = dataInput.readUnsignedShort(); 82 int u2majorVersion = dataInput.readUnsignedShort(); 83 84 programClass.u4version = ClassUtil.internalClassVersion(u2majorVersion, 85 u2minorVersion); 86 87 ClassUtil.checkVersionNumbers(programClass.u4version); 88 89 // Read the constant pool. Note that the first entry is not used. 90 programClass.u2constantPoolCount = dataInput.readUnsignedShort(); 91 92 programClass.constantPool = new Constant[programClass.u2constantPoolCount]; 93 for (int index = 1; index < programClass.u2constantPoolCount; index++) 94 { 95 Constant constant = createConstant(); 96 constant.accept(programClass, this); 97 programClass.constantPool[index] = constant; 98 99 // Long constants and double constants take up two entries in the 100 // constant pool. 101 int tag = constant.getTag(); 102 if (tag == ClassConstants.CONSTANT_Long || 103 tag == ClassConstants.CONSTANT_Double) 104 { 105 programClass.constantPool[++index] = null; 106 } 107 } 108 109 // Read the general class information. 110 programClass.u2accessFlags = dataInput.readUnsignedShort(); 111 programClass.u2thisClass = dataInput.readUnsignedShort(); 112 programClass.u2superClass = dataInput.readUnsignedShort(); 113 114 // Read the interfaces. 115 programClass.u2interfacesCount = dataInput.readUnsignedShort(); 116 117 programClass.u2interfaces = new int[programClass.u2interfacesCount]; 118 for (int index = 0; index < programClass.u2interfacesCount; index++) 119 { 120 programClass.u2interfaces[index] = dataInput.readUnsignedShort(); 121 } 122 123 // Read the fields. 124 programClass.u2fieldsCount = dataInput.readUnsignedShort(); 125 126 programClass.fields = new ProgramField[programClass.u2fieldsCount]; 127 for (int index = 0; index < programClass.u2fieldsCount; index++) 128 { 129 ProgramField programField = new ProgramField(); 130 this.visitProgramField(programClass, programField); 131 programClass.fields[index] = programField; 132 } 133 134 // Read the methods. 135 programClass.u2methodsCount = dataInput.readUnsignedShort(); 136 137 programClass.methods = new ProgramMethod[programClass.u2methodsCount]; 138 for (int index = 0; index < programClass.u2methodsCount; index++) 139 { 140 ProgramMethod programMethod = new ProgramMethod(); 141 this.visitProgramMethod(programClass, programMethod); 142 programClass.methods[index] = programMethod; 143 } 144 145 // Read the class attributes. 146 programClass.u2attributesCount = dataInput.readUnsignedShort(); 147 148 programClass.attributes = new Attribute[programClass.u2attributesCount]; 149 for (int index = 0; index < programClass.u2attributesCount; index++) 150 { 151 Attribute attribute = createAttribute(programClass); 152 attribute.accept(programClass, this); 153 programClass.attributes[index] = attribute; 154 } 155 } 156 157 158 public void visitLibraryClass(LibraryClass libraryClass) 159 { 160 } 161 162 163 // Implementations for MemberVisitor. 164 165 public void visitProgramField(ProgramClass programClass, ProgramField programField) 166 { 167 // Read the general field information. 168 programField.u2accessFlags = dataInput.readUnsignedShort(); 169 programField.u2nameIndex = dataInput.readUnsignedShort(); 170 programField.u2descriptorIndex = dataInput.readUnsignedShort(); 171 172 // Read the field attributes. 173 programField.u2attributesCount = dataInput.readUnsignedShort(); 174 175 programField.attributes = new Attribute[programField.u2attributesCount]; 176 for (int index = 0; index < programField.u2attributesCount; index++) 177 { 178 Attribute attribute = createAttribute(programClass); 179 attribute.accept(programClass, programField, this); 180 programField.attributes[index] = attribute; 181 } 182 } 183 184 185 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 186 { 187 // Read the general method information. 188 programMethod.u2accessFlags = dataInput.readUnsignedShort(); 189 programMethod.u2nameIndex = dataInput.readUnsignedShort(); 190 programMethod.u2descriptorIndex = dataInput.readUnsignedShort(); 191 192 // Read the method attributes. 193 programMethod.u2attributesCount = dataInput.readUnsignedShort(); 194 195 programMethod.attributes = new Attribute[programMethod.u2attributesCount]; 196 for (int index = 0; index < programMethod.u2attributesCount; index++) 197 { 198 Attribute attribute = createAttribute(programClass); 199 attribute.accept(programClass, programMethod, this); 200 programMethod.attributes[index] = attribute; 201 } 202 } 203 204 205 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 206 { 207 } 208 209 210 // Implementations for ConstantVisitor. 211 212 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 213 { 214 integerConstant.u4value = dataInput.readInt(); 215 } 216 217 218 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 219 { 220 longConstant.u8value = dataInput.readLong(); 221 } 222 223 224 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 225 { 226 floatConstant.f4value = dataInput.readFloat(); 227 } 228 229 230 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 231 { 232 doubleConstant.f8value = dataInput.readDouble(); 233 } 234 235 236 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 237 { 238 stringConstant.u2stringIndex = dataInput.readUnsignedShort(); 239 } 240 241 242 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 243 { 244 int u2length = dataInput.readUnsignedShort(); 245 246 // Read the UTF-8 bytes. 247 byte[] bytes = new byte[u2length]; 248 dataInput.readFully(bytes); 249 utf8Constant.setBytes(bytes); 250 } 251 252 253 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 254 { 255 refConstant.u2classIndex = dataInput.readUnsignedShort(); 256 refConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort(); 257 } 258 259 260 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 261 { 262 classConstant.u2nameIndex = dataInput.readUnsignedShort(); 263 } 264 265 266 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 267 { 268 nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort(); 269 nameAndTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort(); 270 } 271 272 273 // Implementations for AttributeVisitor. 274 275 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 276 { 277 // Read the unknown information. 278 byte[] info = new byte[unknownAttribute.u4attributeLength]; 279 dataInput.readFully(info); 280 unknownAttribute.info = info; 281 } 282 283 284 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 285 { 286 sourceFileAttribute.u2sourceFileIndex = dataInput.readUnsignedShort(); 287 } 288 289 290 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 291 { 292 sourceDirAttribute.u2sourceDirIndex = dataInput.readUnsignedShort(); 293 } 294 295 296 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 297 { 298 // Read the inner classes. 299 innerClassesAttribute.u2classesCount = dataInput.readUnsignedShort(); 300 301 innerClassesAttribute.classes = new InnerClassesInfo[innerClassesAttribute.u2classesCount]; 302 for (int index = 0; index < innerClassesAttribute.u2classesCount; index++) 303 { 304 InnerClassesInfo innerClassesInfo = new InnerClassesInfo(); 305 this.visitInnerClassesInfo(clazz, innerClassesInfo); 306 innerClassesAttribute.classes[index] = innerClassesInfo; 307 } 308 } 309 310 311 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 312 { 313 enclosingMethodAttribute.u2classIndex = dataInput.readUnsignedShort(); 314 enclosingMethodAttribute.u2nameAndTypeIndex = dataInput.readUnsignedShort(); 315 } 316 317 318 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 319 { 320 // This attribute does not contain any additional information. 321 } 322 323 324 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 325 { 326 // This attribute does not contain any additional information. 327 } 328 329 330 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 331 { 332 signatureAttribute.u2signatureIndex = dataInput.readUnsignedShort(); 333 } 334 335 336 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 337 { 338 constantValueAttribute.u2constantValueIndex = dataInput.readUnsignedShort(); 339 } 340 341 342 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 343 { 344 // Read the exceptions. 345 exceptionsAttribute.u2exceptionIndexTableLength = dataInput.readUnsignedShort(); 346 347 exceptionsAttribute.u2exceptionIndexTable = new int[exceptionsAttribute.u2exceptionIndexTableLength]; 348 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 349 { 350 exceptionsAttribute.u2exceptionIndexTable[index] = dataInput.readUnsignedShort(); 351 } 352 } 353 354 355 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 356 { 357 // Read the stack size and local variable frame size. 358 codeAttribute.u2maxStack = dataInput.readUnsignedShort(); 359 codeAttribute.u2maxLocals = dataInput.readUnsignedShort(); 360 361 // Read the byte code. 362 codeAttribute.u4codeLength = dataInput.readInt(); 363 364 byte[] code = new byte[codeAttribute.u4codeLength]; 365 dataInput.readFully(code); 366 codeAttribute.code = code; 367 368 // Read the exceptions. 369 codeAttribute.u2exceptionTableLength = dataInput.readUnsignedShort(); 370 371 codeAttribute.exceptionTable = new ExceptionInfo[codeAttribute.u2exceptionTableLength]; 372 for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++) 373 { 374 ExceptionInfo exceptionInfo = new ExceptionInfo(); 375 this.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo); 376 codeAttribute.exceptionTable[index] = exceptionInfo; 377 } 378 379 // Read the code attributes. 380 codeAttribute.u2attributesCount = dataInput.readUnsignedShort(); 381 382 codeAttribute.attributes = new Attribute[codeAttribute.u2attributesCount]; 383 for (int index = 0; index < codeAttribute.u2attributesCount; index++) 384 { 385 Attribute attribute = createAttribute(clazz); 386 attribute.accept(clazz, method, codeAttribute, this); 387 codeAttribute.attributes[index] = attribute; 388 } 389 } 390 391 392 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 393 { 394 // Read the stack map frames (only full frames, without tag). 395 stackMapAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort(); 396 397 stackMapAttribute.stackMapFrames = new FullFrame[stackMapAttribute.u2stackMapFramesCount]; 398 for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++) 399 { 400 FullFrame stackMapFrame = new FullFrame(); 401 this.visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame); 402 stackMapAttribute.stackMapFrames[index] = stackMapFrame; 403 } 404 } 405 406 407 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 408 { 409 // Read the stack map frames. 410 stackMapTableAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort(); 411 412 stackMapTableAttribute.stackMapFrames = new StackMapFrame[stackMapTableAttribute.u2stackMapFramesCount]; 413 for (int index = 0; index < stackMapTableAttribute.u2stackMapFramesCount; index++) 414 { 415 StackMapFrame stackMapFrame = createStackMapFrame(); 416 stackMapFrame.accept(clazz, method, codeAttribute, 0, this); 417 stackMapTableAttribute.stackMapFrames[index] = stackMapFrame; 418 } 419 } 420 421 422 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 423 { 424 // Read the line numbers. 425 lineNumberTableAttribute.u2lineNumberTableLength = dataInput.readUnsignedShort(); 426 427 lineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]; 428 for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++) 429 { 430 LineNumberInfo lineNumberInfo = new LineNumberInfo(); 431 this.visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo); 432 lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo; 433 } 434 } 435 436 437 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 438 { 439 // Read the local variables. 440 localVariableTableAttribute.u2localVariableTableLength = dataInput.readUnsignedShort(); 441 442 localVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]; 443 for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++) 444 { 445 LocalVariableInfo localVariableInfo = new LocalVariableInfo(); 446 this.visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo); 447 localVariableTableAttribute.localVariableTable[index] = localVariableInfo; 448 } 449 } 450 451 452 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 453 { 454 // Read the local variable types. 455 localVariableTypeTableAttribute.u2localVariableTypeTableLength = dataInput.readUnsignedShort(); 456 457 localVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]; 458 for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++) 459 { 460 LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo(); 461 this.visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo); 462 localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo; 463 } 464 } 465 466 467 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 468 { 469 // Read the annotations. 470 annotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort(); 471 472 annotationsAttribute.annotations = new Annotation[annotationsAttribute.u2annotationsCount]; 473 for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++) 474 { 475 Annotation annotation = new Annotation(); 476 this.visitAnnotation(clazz, annotation); 477 annotationsAttribute.annotations[index] = annotation; 478 } 479 } 480 481 482 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 483 { 484 // Read the parameter annotations. 485 parameterAnnotationsAttribute.u2parametersCount = dataInput.readUnsignedByte(); 486 487 // The java compilers of JDK 1.5, JDK 1.6, and Eclipse all count the 488 // number of parameters of constructors of non-static inner classes 489 // incorrectly. Fix it right here. 490 int parameterStart = 0; 491 if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) 492 { 493 int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz)); 494 parameterStart = realParametersCount - parameterAnnotationsAttribute.u2parametersCount; 495 parameterAnnotationsAttribute.u2parametersCount = realParametersCount; 496 } 497 498 parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount]; 499 parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][]; 500 501 for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) 502 { 503 // Read the parameter annotations of the given parameter. 504 int u2annotationsCount = dataInput.readUnsignedShort(); 505 506 Annotation[] annotations = new Annotation[u2annotationsCount]; 507 508 for (int index = 0; index < u2annotationsCount; index++) 509 { 510 Annotation annotation = new Annotation(); 511 this.visitAnnotation(clazz, annotation); 512 annotations[index] = annotation; 513 } 514 515 parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = u2annotationsCount; 516 parameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = annotations; 517 } 518 } 519 520 521 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 522 { 523 // Read the default element value. 524 ElementValue elementValue = createElementValue(); 525 elementValue.accept(clazz, null, this); 526 annotationDefaultAttribute.defaultValue = elementValue; 527 } 528 529 530 // Implementations for InnerClassesInfoVisitor. 531 532 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 533 { 534 innerClassesInfo.u2innerClassIndex = dataInput.readUnsignedShort(); 535 innerClassesInfo.u2outerClassIndex = dataInput.readUnsignedShort(); 536 innerClassesInfo.u2innerNameIndex = dataInput.readUnsignedShort(); 537 innerClassesInfo.u2innerClassAccessFlags = dataInput.readUnsignedShort(); 538 } 539 540 541 // Implementations for ExceptionInfoVisitor. 542 543 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 544 { 545 exceptionInfo.u2startPC = dataInput.readUnsignedShort(); 546 exceptionInfo.u2endPC = dataInput.readUnsignedShort(); 547 exceptionInfo.u2handlerPC = dataInput.readUnsignedShort(); 548 exceptionInfo.u2catchType = dataInput.readUnsignedShort(); 549 } 550 551 552 // Implementations for StackMapFrameVisitor. 553 554 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 555 { 556 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 557 { 558 sameZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); 559 } 560 } 561 562 563 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 564 { 565 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 566 { 567 sameOneFrame.u2offsetDelta = dataInput.readUnsignedShort(); 568 } 569 570 // Read the verification type of the stack entry. 571 VerificationType verificationType = createVerificationType(); 572 verificationType.accept(clazz, method, codeAttribute, offset, this); 573 sameOneFrame.stackItem = verificationType; 574 } 575 576 577 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 578 { 579 lessZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); 580 } 581 582 583 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 584 { 585 moreZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); 586 587 // Read the verification types of the additional local variables. 588 moreZeroFrame.additionalVariables = new VerificationType[moreZeroFrame.additionalVariablesCount]; 589 for (int index = 0; index < moreZeroFrame.additionalVariablesCount; index++) 590 { 591 VerificationType verificationType = createVerificationType(); 592 verificationType.accept(clazz, method, codeAttribute, offset, this); 593 moreZeroFrame.additionalVariables[index] = verificationType; 594 } 595 } 596 597 598 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 599 { 600 fullFrame.u2offsetDelta = dataInput.readUnsignedShort(); 601 602 // Read the verification types of the local variables. 603 fullFrame.variablesCount = dataInput.readUnsignedShort(); 604 fullFrame.variables = new VerificationType[fullFrame.variablesCount]; 605 for (int index = 0; index < fullFrame.variablesCount; index++) 606 { 607 VerificationType verificationType = createVerificationType(); 608 verificationType.variablesAccept(clazz, method, codeAttribute, offset, index, this); 609 fullFrame.variables[index] = verificationType; 610 } 611 612 // Read the verification types of the stack entries. 613 fullFrame.stackCount = dataInput.readUnsignedShort(); 614 fullFrame.stack = new VerificationType[fullFrame.stackCount]; 615 for (int index = 0; index < fullFrame.stackCount; index++) 616 { 617 VerificationType verificationType = createVerificationType(); 618 verificationType.stackAccept(clazz, method, codeAttribute, offset, index, this); 619 fullFrame.stack[index] = verificationType; 620 } 621 } 622 623 624 // Implementations for VerificationTypeVisitor. 625 626 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 627 { 628 // Most verification types don't contain any additional information. 629 } 630 631 632 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 633 { 634 objectType.u2classIndex = dataInput.readUnsignedShort(); 635 } 636 637 638 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 639 { 640 uninitializedType.u2newInstructionOffset = dataInput.readUnsignedShort(); 641 } 642 643 644 // Implementations for LineNumberInfoVisitor. 645 646 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 647 { 648 lineNumberInfo.u2startPC = dataInput.readUnsignedShort(); 649 lineNumberInfo.u2lineNumber = dataInput.readUnsignedShort(); 650 } 651 652 653 // Implementations for LocalVariableInfoVisitor. 654 655 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 656 { 657 localVariableInfo.u2startPC = dataInput.readUnsignedShort(); 658 localVariableInfo.u2length = dataInput.readUnsignedShort(); 659 localVariableInfo.u2nameIndex = dataInput.readUnsignedShort(); 660 localVariableInfo.u2descriptorIndex = dataInput.readUnsignedShort(); 661 localVariableInfo.u2index = dataInput.readUnsignedShort(); 662 } 663 664 665 // Implementations for LocalVariableTypeInfoVisitor. 666 667 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 668 { 669 localVariableTypeInfo.u2startPC = dataInput.readUnsignedShort(); 670 localVariableTypeInfo.u2length = dataInput.readUnsignedShort(); 671 localVariableTypeInfo.u2nameIndex = dataInput.readUnsignedShort(); 672 localVariableTypeInfo.u2signatureIndex = dataInput.readUnsignedShort(); 673 localVariableTypeInfo.u2index = dataInput.readUnsignedShort(); 674 } 675 676 677 // Implementations for AnnotationVisitor. 678 679 public void visitAnnotation(Clazz clazz, Annotation annotation) 680 { 681 // Read the annotation type. 682 annotation.u2typeIndex = dataInput.readUnsignedShort(); 683 684 // Read the element value pairs. 685 annotation.u2elementValuesCount = dataInput.readUnsignedShort(); 686 687 annotation.elementValues = new ElementValue[annotation.u2elementValuesCount]; 688 for (int index = 0; index < annotation.u2elementValuesCount; index++) 689 { 690 int u2elementNameIndex = dataInput.readUnsignedShort(); 691 ElementValue elementValue = createElementValue(); 692 elementValue.u2elementNameIndex = u2elementNameIndex; 693 elementValue.accept(clazz, annotation, this); 694 annotation.elementValues[index] = elementValue; 695 } 696 } 697 698 699 // Implementations for ElementValueVisitor. 700 701 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 702 { 703 constantElementValue.u2constantValueIndex = dataInput.readUnsignedShort(); 704 } 705 706 707 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 708 { 709 enumConstantElementValue.u2typeNameIndex = dataInput.readUnsignedShort(); 710 enumConstantElementValue.u2constantNameIndex = dataInput.readUnsignedShort(); 711 } 712 713 714 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 715 { 716 classElementValue.u2classInfoIndex = dataInput.readUnsignedShort(); 717 } 718 719 720 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 721 { 722 // Read the annotation. 723 Annotation annotationValue = new Annotation(); 724 this.visitAnnotation(clazz, annotationValue); 725 annotationElementValue.annotationValue = annotationValue; 726 } 727 728 729 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 730 { 731 // Read the element values. 732 arrayElementValue.u2elementValuesCount = dataInput.readUnsignedShort(); 733 734 arrayElementValue.elementValues = new ElementValue[arrayElementValue.u2elementValuesCount]; 735 for (int index = 0; index < arrayElementValue.u2elementValuesCount; index++) 736 { 737 ElementValue elementValue = createElementValue(); 738 elementValue.accept(clazz, annotation, this); 739 arrayElementValue.elementValues[index] = elementValue; 740 } 741 } 742 743 744 // Small utility methods. 745 746 private Constant createConstant() 747 { 748 int u1tag = dataInput.readUnsignedByte(); 749 750 switch (u1tag) 751 { 752 case ClassConstants.CONSTANT_Utf8: return new Utf8Constant(); 753 case ClassConstants.CONSTANT_Integer: return new IntegerConstant(); 754 case ClassConstants.CONSTANT_Float: return new FloatConstant(); 755 case ClassConstants.CONSTANT_Long: return new LongConstant(); 756 case ClassConstants.CONSTANT_Double: return new DoubleConstant(); 757 case ClassConstants.CONSTANT_String: return new StringConstant(); 758 case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant(); 759 case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant(); 760 case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant(); 761 case ClassConstants.CONSTANT_Class: return new ClassConstant(); 762 case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant(); 763 764 default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool"); 765 } 766 } 767 768 769 private Attribute createAttribute(Clazz clazz) 770 { 771 int u2attributeNameIndex = dataInput.readUnsignedShort(); 772 int u4attributeLength = dataInput.readInt(); 773 String attributeName = clazz.getString(u2attributeNameIndex); 774 Attribute attribute = 775 attributeName.equals(ClassConstants.ATTR_SourceFile) ? (Attribute)new SourceFileAttribute(): 776 attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute)new SourceDirAttribute(): 777 attributeName.equals(ClassConstants.ATTR_InnerClasses) ? (Attribute)new InnerClassesAttribute(): 778 attributeName.equals(ClassConstants.ATTR_EnclosingMethod) ? (Attribute)new EnclosingMethodAttribute(): 779 attributeName.equals(ClassConstants.ATTR_Deprecated) ? (Attribute)new DeprecatedAttribute(): 780 attributeName.equals(ClassConstants.ATTR_Synthetic) ? (Attribute)new SyntheticAttribute(): 781 attributeName.equals(ClassConstants.ATTR_Signature) ? (Attribute)new SignatureAttribute(): 782 attributeName.equals(ClassConstants.ATTR_ConstantValue) ? (Attribute)new ConstantValueAttribute(): 783 attributeName.equals(ClassConstants.ATTR_Exceptions) ? (Attribute)new ExceptionsAttribute(): 784 attributeName.equals(ClassConstants.ATTR_Code) ? (Attribute)new CodeAttribute(): 785 attributeName.equals(ClassConstants.ATTR_StackMap) ? (Attribute)new StackMapAttribute(): 786 attributeName.equals(ClassConstants.ATTR_StackMapTable) ? (Attribute)new StackMapTableAttribute(): 787 attributeName.equals(ClassConstants.ATTR_LineNumberTable) ? (Attribute)new LineNumberTableAttribute(): 788 attributeName.equals(ClassConstants.ATTR_LocalVariableTable) ? (Attribute)new LocalVariableTableAttribute(): 789 attributeName.equals(ClassConstants.ATTR_LocalVariableTypeTable) ? (Attribute)new LocalVariableTypeTableAttribute(): 790 attributeName.equals(ClassConstants.ATTR_RuntimeVisibleAnnotations) ? (Attribute)new RuntimeVisibleAnnotationsAttribute(): 791 attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute)new RuntimeInvisibleAnnotationsAttribute(): 792 attributeName.equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute)new RuntimeVisibleParameterAnnotationsAttribute(): 793 attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute)new RuntimeInvisibleParameterAnnotationsAttribute(): 794 attributeName.equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute)new AnnotationDefaultAttribute(): 795 (Attribute)new UnknownAttribute(u4attributeLength); 796 attribute.u2attributeNameIndex = u2attributeNameIndex; 797 798 return attribute; 799 } 800 801 802 private StackMapFrame createStackMapFrame() 803 { 804 int u1tag = dataInput.readUnsignedByte(); 805 806 return 807 u1tag < StackMapFrame.SAME_ONE_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) : 808 u1tag < StackMapFrame.SAME_ONE_FRAME_EXTENDED ? (StackMapFrame)new SameOneFrame(u1tag) : 809 u1tag < StackMapFrame.LESS_ZERO_FRAME ? (StackMapFrame)new SameOneFrame(u1tag) : 810 u1tag < StackMapFrame.SAME_ZERO_FRAME_EXTENDED ? (StackMapFrame)new LessZeroFrame(u1tag) : 811 u1tag < StackMapFrame.MORE_ZERO_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) : 812 u1tag < StackMapFrame.FULL_FRAME ? (StackMapFrame)new MoreZeroFrame(u1tag) : 813 (StackMapFrame)new FullFrame(); 814 } 815 816 817 private VerificationType createVerificationType() 818 { 819 int u1tag = dataInput.readUnsignedByte(); 820 821 switch (u1tag) 822 { 823 case VerificationType.INTEGER_TYPE: return new IntegerType(); 824 case VerificationType.FLOAT_TYPE: return new FloatType(); 825 case VerificationType.LONG_TYPE: return new LongType(); 826 case VerificationType.DOUBLE_TYPE: return new DoubleType(); 827 case VerificationType.TOP_TYPE: return new TopType(); 828 case VerificationType.OBJECT_TYPE: return new ObjectType(); 829 case VerificationType.NULL_TYPE: return new NullType(); 830 case VerificationType.UNINITIALIZED_TYPE: return new UninitializedType(); 831 case VerificationType.UNINITIALIZED_THIS_TYPE: return new UninitializedThisType(); 832 833 default: throw new RuntimeException("Unknown verification type ["+u1tag+"] in stack map frame"); 834 } 835 } 836 837 838 private ElementValue createElementValue() 839 { 840 int u1tag = dataInput.readUnsignedByte(); 841 842 switch (u1tag) 843 { 844 case ClassConstants.INTERNAL_TYPE_BOOLEAN: 845 case ClassConstants.INTERNAL_TYPE_BYTE: 846 case ClassConstants.INTERNAL_TYPE_CHAR: 847 case ClassConstants.INTERNAL_TYPE_SHORT: 848 case ClassConstants.INTERNAL_TYPE_INT: 849 case ClassConstants.INTERNAL_TYPE_FLOAT: 850 case ClassConstants.INTERNAL_TYPE_LONG: 851 case ClassConstants.INTERNAL_TYPE_DOUBLE: 852 case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue(u1tag); 853 854 case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue(); 855 case ClassConstants.ELEMENT_VALUE_CLASS: return new ClassElementValue(); 856 case ClassConstants.ELEMENT_VALUE_ANNOTATION: return new AnnotationElementValue(); 857 case ClassConstants.ELEMENT_VALUE_ARRAY: return new ArrayElementValue(); 858 859 default: throw new IllegalArgumentException("Unknown element value tag ["+u1tag+"]"); 860 } 861 } 862} 863