1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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 */ 21 package proguard.classfile.io; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.*; 25 import proguard.classfile.attribute.annotation.*; 26 import proguard.classfile.attribute.annotation.target.*; 27 import proguard.classfile.attribute.annotation.target.visitor.*; 28 import proguard.classfile.attribute.annotation.visitor.*; 29 import proguard.classfile.attribute.preverification.*; 30 import proguard.classfile.attribute.preverification.visitor.*; 31 import proguard.classfile.attribute.visitor.*; 32 import proguard.classfile.constant.*; 33 import proguard.classfile.constant.visitor.ConstantVisitor; 34 import proguard.classfile.util.*; 35 import proguard.classfile.visitor.*; 36 37 import java.io.*; 38 39 /** 40 * This ClassVisitor writes out the ProgramClass objects that it visits to the 41 * given DataOutput object. 42 * 43 * @author Eric Lafortune 44 */ 45 public class ProgramClassWriter 46 extends SimplifiedVisitor 47 implements ClassVisitor, 48 MemberVisitor, 49 ConstantVisitor, 50 AttributeVisitor 51 { 52 private RuntimeDataOutput dataOutput; 53 54 private final ConstantBodyWriter constantBodyWriter = new ConstantBodyWriter(); 55 private final AttributeBodyWriter attributeBodyWriter = new AttributeBodyWriter(); 56 private final StackMapFrameBodyWriter stackMapFrameBodyWriter = new StackMapFrameBodyWriter(); 57 private final VerificationTypeBodyWriter verificationTypeBodyWriter = new VerificationTypeBodyWriter(); 58 private final ElementValueBodyWriter elementValueBodyWriter = new ElementValueBodyWriter(); 59 60 61 /** 62 * Creates a new ProgramClassWriter for writing to the given DataOutput. 63 */ ProgramClassWriter(DataOutput dataOutput)64 public ProgramClassWriter(DataOutput dataOutput) 65 { 66 this.dataOutput = new RuntimeDataOutput(dataOutput); 67 } 68 69 70 // Implementations for ClassVisitor. 71 visitProgramClass(ProgramClass programClass)72 public void visitProgramClass(ProgramClass programClass) 73 { 74 // Write the magic number. 75 dataOutput.writeInt(programClass.u4magic); 76 77 // Write the version numbers. 78 dataOutput.writeShort(ClassUtil.internalMinorClassVersion(programClass.u4version)); 79 dataOutput.writeShort(ClassUtil.internalMajorClassVersion(programClass.u4version)); 80 81 // Write the constant pool. 82 dataOutput.writeShort(programClass.u2constantPoolCount); 83 84 programClass.constantPoolEntriesAccept(this); 85 86 // Write the general class information. 87 dataOutput.writeShort(programClass.u2accessFlags); 88 dataOutput.writeShort(programClass.u2thisClass); 89 dataOutput.writeShort(programClass.u2superClass); 90 91 // Write the interfaces. 92 dataOutput.writeShort(programClass.u2interfacesCount); 93 94 for (int index = 0; index < programClass.u2interfacesCount; index++) 95 { 96 dataOutput.writeShort(programClass.u2interfaces[index]); 97 } 98 99 // Write the fields. 100 dataOutput.writeShort(programClass.u2fieldsCount); 101 102 programClass.fieldsAccept(this); 103 104 // Write the methods. 105 dataOutput.writeShort(programClass.u2methodsCount); 106 107 programClass.methodsAccept(this); 108 109 // Write the class attributes. 110 dataOutput.writeShort(programClass.u2attributesCount); 111 112 programClass.attributesAccept(this); 113 } 114 115 visitLibraryClass(LibraryClass libraryClass)116 public void visitLibraryClass(LibraryClass libraryClass) 117 { 118 } 119 120 121 // Implementations for MemberVisitor. 122 visitProgramField(ProgramClass programClass, ProgramField programField)123 public void visitProgramField(ProgramClass programClass, ProgramField programField) 124 { 125 // Write the general field information. 126 dataOutput.writeShort(programField.u2accessFlags); 127 dataOutput.writeShort(programField.u2nameIndex); 128 dataOutput.writeShort(programField.u2descriptorIndex); 129 130 // Write the field attributes. 131 dataOutput.writeShort(programField.u2attributesCount); 132 133 programField.attributesAccept(programClass, this); 134 } 135 136 visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)137 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 138 { 139 // Write the general method information. 140 dataOutput.writeShort(programMethod.u2accessFlags); 141 dataOutput.writeShort(programMethod.u2nameIndex); 142 dataOutput.writeShort(programMethod.u2descriptorIndex); 143 144 // Write the method attributes. 145 dataOutput.writeShort(programMethod.u2attributesCount); 146 147 programMethod.attributesAccept(programClass, this); 148 } 149 150 visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)151 public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) 152 { 153 } 154 155 156 // Implementations for ConstantVisitor. 157 visitAnyConstant(Clazz clazz, Constant constant)158 public void visitAnyConstant(Clazz clazz, Constant constant) 159 { 160 // Write the tag. 161 dataOutput.writeByte(constant.getTag()); 162 163 // Write the actual body. 164 constant.accept(clazz, constantBodyWriter); 165 } 166 167 168 private class ConstantBodyWriter 169 extends SimplifiedVisitor 170 implements ConstantVisitor 171 { 172 // Implementations for ConstantVisitor. 173 visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)174 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 175 { 176 dataOutput.writeInt(integerConstant.u4value); 177 } 178 179 visitLongConstant(Clazz clazz, LongConstant longConstant)180 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 181 { 182 dataOutput.writeLong(longConstant.u8value); 183 } 184 185 visitFloatConstant(Clazz clazz, FloatConstant floatConstant)186 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 187 { 188 dataOutput.writeFloat(floatConstant.f4value); 189 } 190 191 visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)192 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 193 { 194 dataOutput.writeDouble(doubleConstant.f8value); 195 } 196 197 visitStringConstant(Clazz clazz, StringConstant stringConstant)198 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 199 { 200 dataOutput.writeShort(stringConstant.u2stringIndex); 201 } 202 203 visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)204 public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) 205 { 206 byte[] bytes = utf8Constant.getBytes(); 207 208 dataOutput.writeShort(bytes.length); 209 dataOutput.write(bytes); 210 } 211 212 visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)213 public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) 214 { 215 dataOutput.writeShort(invokeDynamicConstant.u2bootstrapMethodAttributeIndex); 216 dataOutput.writeShort(invokeDynamicConstant.u2nameAndTypeIndex); 217 } 218 219 visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)220 public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) 221 { 222 dataOutput.writeByte(methodHandleConstant.u1referenceKind); 223 dataOutput.writeShort(methodHandleConstant.u2referenceIndex); 224 } 225 226 visitAnyRefConstant(Clazz clazz, RefConstant refConstant)227 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 228 { 229 dataOutput.writeShort(refConstant.u2classIndex); 230 dataOutput.writeShort(refConstant.u2nameAndTypeIndex); 231 } 232 233 visitClassConstant(Clazz clazz, ClassConstant classConstant)234 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 235 { 236 dataOutput.writeShort(classConstant.u2nameIndex); 237 } 238 239 visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)240 public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) 241 { 242 dataOutput.writeShort(methodTypeConstant.u2descriptorIndex); 243 } 244 245 visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)246 public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) 247 { 248 dataOutput.writeShort(nameAndTypeConstant.u2nameIndex); 249 dataOutput.writeShort(nameAndTypeConstant.u2descriptorIndex); 250 } 251 } 252 253 254 // Implementations for AttributeVisitor. 255 visitAnyAttribute(Clazz clazz, Attribute attribute)256 public void visitAnyAttribute(Clazz clazz, Attribute attribute) 257 { 258 // Write the attribute name index. 259 dataOutput.writeShort(attribute.u2attributeNameIndex); 260 261 // We'll write the attribute body into an array first, so we can 262 // automatically figure out its length. 263 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 264 265 // Temporarily replace the current data output. 266 RuntimeDataOutput oldDataOutput = dataOutput; 267 dataOutput = new RuntimeDataOutput(new DataOutputStream(byteArrayOutputStream)); 268 269 // Write the attribute body into the array. Note that the 270 // accept method with two dummy null arguments never throws 271 // an UnsupportedOperationException. 272 attribute.accept(clazz, null, null, attributeBodyWriter); 273 274 // Restore the original data output. 275 dataOutput = oldDataOutput; 276 277 // Write the attribute length and body. 278 byte[] info = byteArrayOutputStream.toByteArray(); 279 280 dataOutput.writeInt(info.length); 281 dataOutput.write(info); 282 } 283 284 285 private class AttributeBodyWriter 286 extends SimplifiedVisitor 287 implements AttributeVisitor, 288 BootstrapMethodInfoVisitor, 289 InnerClassesInfoVisitor, 290 ExceptionInfoVisitor, 291 StackMapFrameVisitor, 292 VerificationTypeVisitor, 293 LineNumberInfoVisitor, 294 ParameterInfoVisitor, 295 LocalVariableInfoVisitor, 296 LocalVariableTypeInfoVisitor, 297 AnnotationVisitor, 298 TypeAnnotationVisitor, 299 TargetInfoVisitor, 300 TypePathInfoVisitor, 301 LocalVariableTargetElementVisitor, 302 ElementValueVisitor 303 { 304 // Implementations for AttributeVisitor. 305 visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)306 public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) 307 { 308 // Write the unknown information. 309 dataOutput.write(unknownAttribute.info); 310 } 311 312 visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)313 public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) 314 { 315 // Write the bootstrap methods. 316 dataOutput.writeShort(bootstrapMethodsAttribute.u2bootstrapMethodsCount); 317 318 bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this); 319 } 320 321 visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)322 public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) 323 { 324 dataOutput.writeShort(sourceFileAttribute.u2sourceFileIndex); 325 } 326 327 visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)328 public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) 329 { 330 dataOutput.writeShort(sourceDirAttribute.u2sourceDirIndex); 331 } 332 333 visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)334 public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 335 { 336 // Write the inner classes. 337 dataOutput.writeShort(innerClassesAttribute.u2classesCount); 338 339 innerClassesAttribute.innerClassEntriesAccept(clazz, this); 340 } 341 342 visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)343 public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 344 { 345 dataOutput.writeShort(enclosingMethodAttribute.u2classIndex); 346 dataOutput.writeShort(enclosingMethodAttribute.u2nameAndTypeIndex); 347 } 348 349 visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)350 public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) 351 { 352 // This attribute does not contain any additional information. 353 } 354 355 visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)356 public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) 357 { 358 // This attribute does not contain any additional information. 359 } 360 361 visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)362 public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) 363 { 364 dataOutput.writeShort(signatureAttribute.u2signatureIndex); 365 } 366 367 visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)368 public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) 369 { 370 dataOutput.writeShort(constantValueAttribute.u2constantValueIndex); 371 } 372 373 visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)374 public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) 375 { 376 // Write the parameter information. 377 dataOutput.writeByte(methodParametersAttribute.u1parametersCount); 378 379 methodParametersAttribute.parametersAccept(clazz, method, this); 380 } 381 382 visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)383 public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) 384 { 385 // Write the exceptions. 386 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTableLength); 387 388 for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) 389 { 390 dataOutput.writeShort(exceptionsAttribute.u2exceptionIndexTable[index]); 391 } 392 } 393 394 visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)395 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 396 { 397 // Write the stack size and local variable frame size. 398 dataOutput.writeShort(codeAttribute.u2maxStack); 399 dataOutput.writeShort(codeAttribute.u2maxLocals); 400 401 // Write the byte code. 402 dataOutput.writeInt(codeAttribute.u4codeLength); 403 404 dataOutput.write(codeAttribute.code, 0, codeAttribute.u4codeLength); 405 406 // Write the exceptions. 407 dataOutput.writeShort(codeAttribute.u2exceptionTableLength); 408 409 codeAttribute.exceptionsAccept(clazz, method, this); 410 411 // Write the code attributes. 412 dataOutput.writeShort(codeAttribute.u2attributesCount); 413 414 codeAttribute.attributesAccept(clazz, method, ProgramClassWriter.this); 415 } 416 417 visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)418 public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 419 { 420 // Write the stack map frames (only full frames, without tag). 421 dataOutput.writeShort(stackMapAttribute.u2stackMapFramesCount); 422 423 stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, stackMapFrameBodyWriter); 424 } 425 426 visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)427 public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 428 { 429 // Write the stack map frames. 430 dataOutput.writeShort(stackMapTableAttribute.u2stackMapFramesCount); 431 432 stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 433 } 434 435 visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)436 public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 437 { 438 // Write the line numbers. 439 dataOutput.writeShort(lineNumberTableAttribute.u2lineNumberTableLength); 440 441 lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 442 } 443 444 visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)445 public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 446 { 447 // Write the local variables. 448 dataOutput.writeShort(localVariableTableAttribute.u2localVariableTableLength); 449 450 localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 451 } 452 453 visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)454 public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 455 { 456 // Write the local variable types. 457 dataOutput.writeShort(localVariableTypeTableAttribute.u2localVariableTypeTableLength); 458 459 localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 460 } 461 462 visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)463 public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) 464 { 465 // Write the annotations. 466 dataOutput.writeShort(annotationsAttribute.u2annotationsCount); 467 468 annotationsAttribute.annotationsAccept(clazz, this); 469 } 470 471 visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)472 public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) 473 { 474 // Write the parameter annotations. 475 dataOutput.writeByte(parameterAnnotationsAttribute.u1parametersCount); 476 477 for (int parameterIndex = 0; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) 478 { 479 // Write the parameter annotations of the given parameter. 480 int u2annotationsCount = parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; 481 Annotation[] annotations = parameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; 482 483 dataOutput.writeShort(u2annotationsCount); 484 485 for (int index = 0; index < u2annotationsCount; index++) 486 { 487 visitAnnotation(clazz, annotations[index]); 488 } 489 490 } 491 } 492 493 visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute)494 public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) 495 { 496 // Write the type annotations. 497 dataOutput.writeShort(typeAnnotationsAttribute.u2annotationsCount); 498 499 typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); 500 } 501 502 visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)503 public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) 504 { 505 // Write the default element value. 506 annotationDefaultAttribute.defaultValue.accept(clazz, null, this); 507 } 508 509 510 // Implementations for BootstrapMethodInfoVisitor. 511 visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)512 public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) 513 { 514 dataOutput.writeShort(bootstrapMethodInfo.u2methodHandleIndex); 515 516 // Write the bootstrap method arguments. 517 dataOutput.writeShort(bootstrapMethodInfo.u2methodArgumentCount); 518 519 for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++) 520 { 521 dataOutput.writeShort(bootstrapMethodInfo.u2methodArguments[index]); 522 } 523 } 524 525 526 // Implementations for InnerClassesInfoVisitor. 527 visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)528 public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 529 { 530 dataOutput.writeShort(innerClassesInfo.u2innerClassIndex); 531 dataOutput.writeShort(innerClassesInfo.u2outerClassIndex); 532 dataOutput.writeShort(innerClassesInfo.u2innerNameIndex); 533 dataOutput.writeShort(innerClassesInfo.u2innerClassAccessFlags); 534 } 535 536 537 // Implementations for ExceptionInfoVisitor. 538 visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)539 public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 540 { 541 dataOutput.writeShort(exceptionInfo.u2startPC); 542 dataOutput.writeShort(exceptionInfo.u2endPC); 543 dataOutput.writeShort(exceptionInfo.u2handlerPC); 544 dataOutput.writeShort(exceptionInfo.u2catchType); 545 } 546 547 548 // Implementations for StackMapFrameVisitor. 549 visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)550 public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 551 { 552 // Write the stack map frame tag. 553 dataOutput.writeByte(stackMapFrame.getTag()); 554 555 // Write the actual body. 556 stackMapFrame.accept(clazz, method, codeAttribute, offset, stackMapFrameBodyWriter); 557 } 558 559 560 // Implementations for LineNumberInfoVisitor. 561 visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)562 public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 563 { 564 dataOutput.writeShort(lineNumberInfo.u2startPC); 565 dataOutput.writeShort(lineNumberInfo.u2lineNumber); 566 } 567 568 569 // Implementations for ParameterInfoVisitor. 570 visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)571 public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) 572 { 573 dataOutput.writeShort(parameterInfo.u2nameIndex); 574 dataOutput.writeShort(parameterInfo.u2accessFlags); 575 } 576 577 578 // Implementations for LocalVariableInfoVisitor. 579 visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)580 public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 581 { 582 dataOutput.writeShort(localVariableInfo.u2startPC); 583 dataOutput.writeShort(localVariableInfo.u2length); 584 dataOutput.writeShort(localVariableInfo.u2nameIndex); 585 dataOutput.writeShort(localVariableInfo.u2descriptorIndex); 586 dataOutput.writeShort(localVariableInfo.u2index); 587 } 588 589 590 // Implementations for LocalVariableTypeInfoVisitor. 591 visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)592 public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 593 { 594 dataOutput.writeShort(localVariableTypeInfo.u2startPC); 595 dataOutput.writeShort(localVariableTypeInfo.u2length); 596 dataOutput.writeShort(localVariableTypeInfo.u2nameIndex); 597 dataOutput.writeShort(localVariableTypeInfo.u2signatureIndex); 598 dataOutput.writeShort(localVariableTypeInfo.u2index); 599 } 600 601 602 // Implementations for AnnotationVisitor. 603 visitAnnotation(Clazz clazz, Annotation annotation)604 public void visitAnnotation(Clazz clazz, Annotation annotation) 605 { 606 // Write the annotation type. 607 dataOutput.writeShort(annotation.u2typeIndex); 608 609 // Write the element value pairs. 610 dataOutput.writeShort(annotation.u2elementValuesCount); 611 612 annotation.elementValuesAccept(clazz, this); 613 } 614 615 616 // Implementations for TypeAnnotationVisitor. 617 visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)618 public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) 619 { 620 // Write the target info. 621 dataOutput.writeByte(typeAnnotation.targetInfo.u1targetType); 622 623 typeAnnotation.targetInfoAccept(clazz, this); 624 625 // Write the type path. 626 dataOutput.writeByte(typeAnnotation.typePath.length); 627 628 typeAnnotation.typePathInfosAccept(clazz, this); 629 630 // Write the actual annotation. 631 visitAnnotation(clazz, typeAnnotation); 632 } 633 634 635 // Implementations for TargetInfoVisitor. 636 visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)637 public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) 638 { 639 dataOutput.writeByte(typeParameterTargetInfo.u1typeParameterIndex); 640 } 641 642 visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)643 public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) 644 { 645 dataOutput.writeShort(superTypeTargetInfo.u2superTypeIndex); 646 } 647 648 visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)649 public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) 650 { 651 dataOutput.writeByte(typeParameterBoundTargetInfo.u1typeParameterIndex); 652 dataOutput.writeByte(typeParameterBoundTargetInfo.u1boundIndex); 653 } 654 655 visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)656 public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) 657 { 658 } 659 660 visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)661 public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) 662 { 663 dataOutput.writeByte(formalParameterTargetInfo.u1formalParameterIndex); 664 } 665 666 visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)667 public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) 668 { 669 dataOutput.writeShort(throwsTargetInfo.u2throwsTypeIndex); 670 } 671 672 visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)673 public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) 674 { 675 // Write the local variable target elements. 676 dataOutput.writeShort(localVariableTargetInfo.u2tableLength); 677 678 localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); 679 } 680 681 visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)682 public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) 683 { 684 dataOutput.writeShort(catchTargetInfo.u2exceptionTableIndex); 685 } 686 687 visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)688 public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) 689 { 690 dataOutput.writeShort(offsetTargetInfo.u2offset); 691 } 692 693 visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)694 public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) 695 { 696 dataOutput.writeShort(typeArgumentTargetInfo.u2offset); 697 dataOutput.writeByte(typeArgumentTargetInfo.u1typeArgumentIndex); 698 } 699 700 701 // Implementations for TypePathInfoVisitor. 702 visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)703 public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) 704 { 705 dataOutput.writeByte(typePathInfo.u1typePathKind); 706 dataOutput.writeByte(typePathInfo.u1typeArgumentIndex); 707 } 708 709 710 // Implementations for LocalVariableTargetElementVisitor. 711 visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)712 public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) 713 { 714 dataOutput.writeShort(localVariableTargetElement.u2startPC); 715 dataOutput.writeShort(localVariableTargetElement.u2length); 716 dataOutput.writeShort(localVariableTargetElement.u2index); 717 } 718 719 720 // Implementations for ElementValueVisitor. 721 visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue)722 public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) 723 { 724 // Write the element name index, if applicable. 725 int u2elementNameIndex = elementValue.u2elementNameIndex; 726 if (u2elementNameIndex != 0) 727 { 728 dataOutput.writeShort(u2elementNameIndex); 729 } 730 731 // Write the tag. 732 dataOutput.writeByte(elementValue.getTag()); 733 734 // Write the actual body. 735 elementValue.accept(clazz, annotation, elementValueBodyWriter); 736 } 737 } 738 739 740 private class StackMapFrameBodyWriter 741 extends SimplifiedVisitor 742 implements StackMapFrameVisitor, 743 VerificationTypeVisitor 744 { visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)745 public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) 746 { 747 if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) 748 { 749 dataOutput.writeShort(sameZeroFrame.u2offsetDelta); 750 } 751 } 752 753 visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)754 public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 755 { 756 if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) 757 { 758 dataOutput.writeShort(sameOneFrame.u2offsetDelta); 759 } 760 761 // Write the verification type of the stack entry. 762 sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 763 } 764 765 visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)766 public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) 767 { 768 dataOutput.writeShort(lessZeroFrame.u2offsetDelta); 769 } 770 771 visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)772 public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 773 { 774 dataOutput.writeShort(moreZeroFrame.u2offsetDelta); 775 776 // Write the verification types of the additional local variables. 777 moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 778 } 779 780 visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)781 public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 782 { 783 dataOutput.writeShort(fullFrame.u2offsetDelta); 784 785 // Write the verification types of the local variables. 786 dataOutput.writeShort(fullFrame.variablesCount); 787 fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 788 789 // Write the verification types of the stack entries. 790 dataOutput.writeShort(fullFrame.stackCount); 791 fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 792 } 793 794 795 // Implementations for VerificationTypeVisitor. 796 visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)797 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 798 { 799 // Write the verification type tag. 800 dataOutput.writeByte(verificationType.getTag()); 801 802 // Write the actual body. 803 verificationType.accept(clazz, method, codeAttribute, offset, verificationTypeBodyWriter); 804 } 805 } 806 807 808 private class VerificationTypeBodyWriter 809 extends SimplifiedVisitor 810 implements VerificationTypeVisitor 811 { 812 // Implementations for VerificationTypeVisitor. 813 visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType)814 public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) 815 { 816 // Most verification types don't contain any additional information. 817 } 818 819 visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)820 public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) 821 { 822 dataOutput.writeShort(objectType.u2classIndex); 823 } 824 825 visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)826 public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 827 { 828 dataOutput.writeShort(uninitializedType.u2newInstructionOffset); 829 } 830 } 831 832 833 private class ElementValueBodyWriter 834 extends SimplifiedVisitor 835 implements ElementValueVisitor 836 { 837 // Implementations for ElementValueVisitor. 838 visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)839 public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) 840 { 841 dataOutput.writeShort(constantElementValue.u2constantValueIndex); 842 } 843 844 visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)845 public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) 846 { 847 dataOutput.writeShort(enumConstantElementValue.u2typeNameIndex); 848 dataOutput.writeShort(enumConstantElementValue.u2constantNameIndex); 849 } 850 851 visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)852 public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) 853 { 854 dataOutput.writeShort(classElementValue.u2classInfoIndex); 855 } 856 857 visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)858 public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) 859 { 860 // Write the annotation. 861 attributeBodyWriter.visitAnnotation(clazz, annotationElementValue.annotationValue); 862 } 863 864 visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)865 public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) 866 { 867 // Write the element values. 868 dataOutput.writeShort(arrayElementValue.u2elementValuesCount); 869 870 arrayElementValue.elementValuesAccept(clazz, annotation, attributeBodyWriter); 871 } 872 } 873 } 874