1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm.tree; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 import org.objectweb.asm.AnnotationVisitor; 33 import org.objectweb.asm.Attribute; 34 import org.objectweb.asm.ClassVisitor; 35 import org.objectweb.asm.ConstantDynamic; 36 import org.objectweb.asm.Handle; 37 import org.objectweb.asm.Label; 38 import org.objectweb.asm.MethodVisitor; 39 import org.objectweb.asm.Opcodes; 40 import org.objectweb.asm.Type; 41 import org.objectweb.asm.TypePath; 42 43 /** 44 * A node that represents a method. 45 * 46 * @author Eric Bruneton 47 */ 48 public class MethodNode extends MethodVisitor { 49 50 /** 51 * The method's access flags (see {@link Opcodes}). This field also indicates if the method is 52 * synthetic and/or deprecated. 53 */ 54 public int access; 55 56 /** The method's name. */ 57 public String name; 58 59 /** The method's descriptor (see {@link Type}). */ 60 public String desc; 61 62 /** The method's signature. May be {@literal null}. */ 63 public String signature; 64 65 /** The internal names of the method's exception classes (see {@link Type#getInternalName()}). */ 66 public List<String> exceptions; 67 68 /** The method parameter info (access flags and name). */ 69 public List<ParameterNode> parameters; 70 71 /** The runtime visible annotations of this method. May be {@literal null}. */ 72 public List<AnnotationNode> visibleAnnotations; 73 74 /** The runtime invisible annotations of this method. May be {@literal null}. */ 75 public List<AnnotationNode> invisibleAnnotations; 76 77 /** The runtime visible type annotations of this method. May be {@literal null}. */ 78 public List<TypeAnnotationNode> visibleTypeAnnotations; 79 80 /** The runtime invisible type annotations of this method. May be {@literal null}. */ 81 public List<TypeAnnotationNode> invisibleTypeAnnotations; 82 83 /** The non standard attributes of this method. May be {@literal null}. */ 84 public List<Attribute> attrs; 85 86 /** 87 * The default value of this annotation interface method. This field must be a {@link Byte}, 88 * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}, {@link Long}, {@link 89 * Float}, {@link Double}, {@link String} or {@link Type}, or an two elements String array (for 90 * enumeration values), a {@link AnnotationNode}, or a {@link List} of values of one of the 91 * preceding types. May be {@literal null}. 92 */ 93 public Object annotationDefault; 94 95 /** 96 * The number of method parameters than can have runtime visible annotations. This number must be 97 * less or equal than the number of parameter types in the method descriptor (the default value 0 98 * indicates that all the parameters described in the method descriptor can have annotations). It 99 * can be strictly less when a method has synthetic parameters and when these parameters are 100 * ignored when computing parameter indices for the purpose of parameter annotations (see 101 * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18). 102 */ 103 public int visibleAnnotableParameterCount; 104 105 /** 106 * The runtime visible parameter annotations of this method. These lists are lists of {@link 107 * AnnotationNode} objects. May be {@literal null}. 108 */ 109 public List<AnnotationNode>[] visibleParameterAnnotations; 110 111 /** 112 * The number of method parameters than can have runtime invisible annotations. This number must 113 * be less or equal than the number of parameter types in the method descriptor (the default value 114 * 0 indicates that all the parameters described in the method descriptor can have annotations). 115 * It can be strictly less when a method has synthetic parameters and when these parameters are 116 * ignored when computing parameter indices for the purpose of parameter annotations (see 117 * https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.18). 118 */ 119 public int invisibleAnnotableParameterCount; 120 121 /** 122 * The runtime invisible parameter annotations of this method. These lists are lists of {@link 123 * AnnotationNode} objects. May be {@literal null}. 124 */ 125 public List<AnnotationNode>[] invisibleParameterAnnotations; 126 127 /** The instructions of this method. */ 128 public InsnList instructions; 129 130 /** The try catch blocks of this method. */ 131 public List<TryCatchBlockNode> tryCatchBlocks; 132 133 /** The maximum stack size of this method. */ 134 public int maxStack; 135 136 /** The maximum number of local variables of this method. */ 137 public int maxLocals; 138 139 /** The local variables of this method. May be {@literal null} */ 140 public List<LocalVariableNode> localVariables; 141 142 /** The visible local variable annotations of this method. May be {@literal null} */ 143 public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations; 144 145 /** The invisible local variable annotations of this method. May be {@literal null} */ 146 public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations; 147 148 /** Whether the accept method has been called on this object. */ 149 private boolean visited; 150 151 /** 152 * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not use this 153 * constructor</i>. Instead, they must use the {@link #MethodNode(int)} version. 154 * 155 * @throws IllegalStateException If a subclass calls this constructor. 156 */ MethodNode()157 public MethodNode() { 158 this(/* latest api = */ Opcodes.ASM9); 159 if (getClass() != MethodNode.class) { 160 throw new IllegalStateException(); 161 } 162 } 163 164 /** 165 * Constructs an uninitialized {@link MethodNode}. 166 * 167 * @param api the ASM API version implemented by this visitor. Must be one of the {@code 168 * ASM}<i>x</i> values in {@link Opcodes}. 169 */ MethodNode(final int api)170 public MethodNode(final int api) { 171 super(api); 172 this.instructions = new InsnList(); 173 } 174 175 /** 176 * Constructs a new {@link MethodNode}. <i>Subclasses must not use this constructor</i>. Instead, 177 * they must use the {@link #MethodNode(int, int, String, String, String, String[])} version. 178 * 179 * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if 180 * the method is synthetic and/or deprecated. 181 * @param name the method's name. 182 * @param descriptor the method's descriptor (see {@link Type}). 183 * @param signature the method's signature. May be {@literal null}. 184 * @param exceptions the internal names of the method's exception classes (see {@link 185 * Type#getInternalName()}). May be {@literal null}. 186 * @throws IllegalStateException If a subclass calls this constructor. 187 */ MethodNode( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)188 public MethodNode( 189 final int access, 190 final String name, 191 final String descriptor, 192 final String signature, 193 final String[] exceptions) { 194 this(/* latest api = */ Opcodes.ASM9, access, name, descriptor, signature, exceptions); 195 if (getClass() != MethodNode.class) { 196 throw new IllegalStateException(); 197 } 198 } 199 200 /** 201 * Constructs a new {@link MethodNode}. 202 * 203 * @param api the ASM API version implemented by this visitor. Must be one of the {@code 204 * ASM}<i>x</i> values in {@link Opcodes}. 205 * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if 206 * the method is synthetic and/or deprecated. 207 * @param name the method's name. 208 * @param descriptor the method's descriptor (see {@link Type}). 209 * @param signature the method's signature. May be {@literal null}. 210 * @param exceptions the internal names of the method's exception classes (see {@link 211 * Type#getInternalName()}). May be {@literal null}. 212 */ MethodNode( final int api, final int access, final String name, final String descriptor, final String signature, final String[] exceptions)213 public MethodNode( 214 final int api, 215 final int access, 216 final String name, 217 final String descriptor, 218 final String signature, 219 final String[] exceptions) { 220 super(api); 221 this.access = access; 222 this.name = name; 223 this.desc = descriptor; 224 this.signature = signature; 225 this.exceptions = Util.asArrayList(exceptions); 226 if ((access & Opcodes.ACC_ABSTRACT) == 0) { 227 this.localVariables = new ArrayList<>(5); 228 } 229 this.tryCatchBlocks = new ArrayList<>(); 230 this.instructions = new InsnList(); 231 } 232 233 // ----------------------------------------------------------------------------------------------- 234 // Implementation of the MethodVisitor abstract class 235 // ----------------------------------------------------------------------------------------------- 236 237 @Override visitParameter(final String name, final int access)238 public void visitParameter(final String name, final int access) { 239 if (parameters == null) { 240 parameters = new ArrayList<>(5); 241 } 242 parameters.add(new ParameterNode(name, access)); 243 } 244 245 @Override 246 @SuppressWarnings("serial") visitAnnotationDefault()247 public AnnotationVisitor visitAnnotationDefault() { 248 return new AnnotationNode( 249 new ArrayList<Object>(0) { 250 @Override 251 public boolean add(final Object o) { 252 annotationDefault = o; 253 return super.add(o); 254 } 255 }); 256 } 257 258 @Override 259 public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 260 AnnotationNode annotation = new AnnotationNode(descriptor); 261 if (visible) { 262 visibleAnnotations = Util.add(visibleAnnotations, annotation); 263 } else { 264 invisibleAnnotations = Util.add(invisibleAnnotations, annotation); 265 } 266 return annotation; 267 } 268 269 @Override 270 public AnnotationVisitor visitTypeAnnotation( 271 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 272 TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor); 273 if (visible) { 274 visibleTypeAnnotations = Util.add(visibleTypeAnnotations, typeAnnotation); 275 } else { 276 invisibleTypeAnnotations = Util.add(invisibleTypeAnnotations, typeAnnotation); 277 } 278 return typeAnnotation; 279 } 280 281 @Override 282 public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) { 283 if (visible) { 284 visibleAnnotableParameterCount = parameterCount; 285 } else { 286 invisibleAnnotableParameterCount = parameterCount; 287 } 288 } 289 290 @Override 291 @SuppressWarnings("unchecked") 292 public AnnotationVisitor visitParameterAnnotation( 293 final int parameter, final String descriptor, final boolean visible) { 294 AnnotationNode annotation = new AnnotationNode(descriptor); 295 if (visible) { 296 if (visibleParameterAnnotations == null) { 297 int params = Type.getArgumentCount(desc); 298 visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 299 } 300 visibleParameterAnnotations[parameter] = 301 Util.add(visibleParameterAnnotations[parameter], annotation); 302 } else { 303 if (invisibleParameterAnnotations == null) { 304 int params = Type.getArgumentCount(desc); 305 invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params]; 306 } 307 invisibleParameterAnnotations[parameter] = 308 Util.add(invisibleParameterAnnotations[parameter], annotation); 309 } 310 return annotation; 311 } 312 313 @Override 314 public void visitAttribute(final Attribute attribute) { 315 attrs = Util.add(attrs, attribute); 316 } 317 318 @Override 319 public void visitCode() { 320 // Nothing to do. 321 } 322 323 @Override 324 public void visitFrame( 325 final int type, 326 final int numLocal, 327 final Object[] local, 328 final int numStack, 329 final Object[] stack) { 330 instructions.add( 331 new FrameNode( 332 type, 333 numLocal, 334 local == null ? null : getLabelNodes(local), 335 numStack, 336 stack == null ? null : getLabelNodes(stack))); 337 } 338 339 @Override 340 public void visitInsn(final int opcode) { 341 instructions.add(new InsnNode(opcode)); 342 } 343 344 @Override 345 public void visitIntInsn(final int opcode, final int operand) { 346 instructions.add(new IntInsnNode(opcode, operand)); 347 } 348 349 @Override 350 public void visitVarInsn(final int opcode, final int varIndex) { 351 instructions.add(new VarInsnNode(opcode, varIndex)); 352 } 353 354 @Override 355 public void visitTypeInsn(final int opcode, final String type) { 356 instructions.add(new TypeInsnNode(opcode, type)); 357 } 358 359 @Override 360 public void visitFieldInsn( 361 final int opcode, final String owner, final String name, final String descriptor) { 362 instructions.add(new FieldInsnNode(opcode, owner, name, descriptor)); 363 } 364 365 @Override 366 public void visitMethodInsn( 367 final int opcodeAndSource, 368 final String owner, 369 final String name, 370 final String descriptor, 371 final boolean isInterface) { 372 if (api < Opcodes.ASM5 && (opcodeAndSource & Opcodes.SOURCE_DEPRECATED) == 0) { 373 // Redirect the call to the deprecated version of this method. 374 super.visitMethodInsn(opcodeAndSource, owner, name, descriptor, isInterface); 375 return; 376 } 377 int opcode = opcodeAndSource & ~Opcodes.SOURCE_MASK; 378 379 instructions.add(new MethodInsnNode(opcode, owner, name, descriptor, isInterface)); 380 } 381 382 @Override 383 public void visitInvokeDynamicInsn( 384 final String name, 385 final String descriptor, 386 final Handle bootstrapMethodHandle, 387 final Object... bootstrapMethodArguments) { 388 instructions.add( 389 new InvokeDynamicInsnNode( 390 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)); 391 } 392 393 @Override 394 public void visitJumpInsn(final int opcode, final Label label) { 395 instructions.add(new JumpInsnNode(opcode, getLabelNode(label))); 396 } 397 398 @Override 399 public void visitLabel(final Label label) { 400 instructions.add(getLabelNode(label)); 401 } 402 403 @Override 404 public void visitLdcInsn(final Object value) { 405 instructions.add(new LdcInsnNode(value)); 406 } 407 408 @Override 409 public void visitIincInsn(final int varIndex, final int increment) { 410 instructions.add(new IincInsnNode(varIndex, increment)); 411 } 412 413 @Override 414 public void visitTableSwitchInsn( 415 final int min, final int max, final Label dflt, final Label... labels) { 416 instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt), getLabelNodes(labels))); 417 } 418 419 @Override 420 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { 421 instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys, getLabelNodes(labels))); 422 } 423 424 @Override 425 public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { 426 instructions.add(new MultiANewArrayInsnNode(descriptor, numDimensions)); 427 } 428 429 @Override 430 public AnnotationVisitor visitInsnAnnotation( 431 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 432 // Find the last real instruction, i.e. the instruction targeted by this annotation. 433 AbstractInsnNode currentInsn = instructions.getLast(); 434 while (currentInsn.getOpcode() == -1) { 435 currentInsn = currentInsn.getPrevious(); 436 } 437 // Add the annotation to this instruction. 438 TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor); 439 if (visible) { 440 currentInsn.visibleTypeAnnotations = 441 Util.add(currentInsn.visibleTypeAnnotations, typeAnnotation); 442 } else { 443 currentInsn.invisibleTypeAnnotations = 444 Util.add(currentInsn.invisibleTypeAnnotations, typeAnnotation); 445 } 446 return typeAnnotation; 447 } 448 449 @Override 450 public void visitTryCatchBlock( 451 final Label start, final Label end, final Label handler, final String type) { 452 TryCatchBlockNode tryCatchBlock = 453 new TryCatchBlockNode(getLabelNode(start), getLabelNode(end), getLabelNode(handler), type); 454 tryCatchBlocks = Util.add(tryCatchBlocks, tryCatchBlock); 455 } 456 457 @Override 458 public AnnotationVisitor visitTryCatchAnnotation( 459 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 460 TryCatchBlockNode tryCatchBlock = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8); 461 TypeAnnotationNode typeAnnotation = new TypeAnnotationNode(typeRef, typePath, descriptor); 462 if (visible) { 463 tryCatchBlock.visibleTypeAnnotations = 464 Util.add(tryCatchBlock.visibleTypeAnnotations, typeAnnotation); 465 } else { 466 tryCatchBlock.invisibleTypeAnnotations = 467 Util.add(tryCatchBlock.invisibleTypeAnnotations, typeAnnotation); 468 } 469 return typeAnnotation; 470 } 471 472 @Override 473 public void visitLocalVariable( 474 final String name, 475 final String descriptor, 476 final String signature, 477 final Label start, 478 final Label end, 479 final int index) { 480 LocalVariableNode localVariable = 481 new LocalVariableNode( 482 name, descriptor, signature, getLabelNode(start), getLabelNode(end), index); 483 localVariables = Util.add(localVariables, localVariable); 484 } 485 486 @Override 487 public AnnotationVisitor visitLocalVariableAnnotation( 488 final int typeRef, 489 final TypePath typePath, 490 final Label[] start, 491 final Label[] end, 492 final int[] index, 493 final String descriptor, 494 final boolean visible) { 495 LocalVariableAnnotationNode localVariableAnnotation = 496 new LocalVariableAnnotationNode( 497 typeRef, typePath, getLabelNodes(start), getLabelNodes(end), index, descriptor); 498 if (visible) { 499 visibleLocalVariableAnnotations = 500 Util.add(visibleLocalVariableAnnotations, localVariableAnnotation); 501 } else { 502 invisibleLocalVariableAnnotations = 503 Util.add(invisibleLocalVariableAnnotations, localVariableAnnotation); 504 } 505 return localVariableAnnotation; 506 } 507 508 @Override 509 public void visitLineNumber(final int line, final Label start) { 510 instructions.add(new LineNumberNode(line, getLabelNode(start))); 511 } 512 513 @Override 514 public void visitMaxs(final int maxStack, final int maxLocals) { 515 this.maxStack = maxStack; 516 this.maxLocals = maxLocals; 517 } 518 519 @Override 520 public void visitEnd() { 521 // Nothing to do. 522 } 523 524 /** 525 * Returns the LabelNode corresponding to the given Label. Creates a new LabelNode if necessary. 526 * The default implementation of this method uses the {@link Label#info} field to store 527 * associations between labels and label nodes. 528 * 529 * @param label a Label. 530 * @return the LabelNode corresponding to label. 531 */ 532 protected LabelNode getLabelNode(final Label label) { 533 if (!(label.info instanceof LabelNode)) { 534 label.info = new LabelNode(); 535 } 536 return (LabelNode) label.info; 537 } 538 539 private LabelNode[] getLabelNodes(final Label[] labels) { 540 LabelNode[] labelNodes = new LabelNode[labels.length]; 541 for (int i = 0, n = labels.length; i < n; ++i) { 542 labelNodes[i] = getLabelNode(labels[i]); 543 } 544 return labelNodes; 545 } 546 547 private Object[] getLabelNodes(final Object[] objects) { 548 Object[] labelNodes = new Object[objects.length]; 549 for (int i = 0, n = objects.length; i < n; ++i) { 550 Object o = objects[i]; 551 if (o instanceof Label) { 552 o = getLabelNode((Label) o); 553 } 554 labelNodes[i] = o; 555 } 556 return labelNodes; 557 } 558 559 // ----------------------------------------------------------------------------------------------- 560 // Accept method 561 // ----------------------------------------------------------------------------------------------- 562 563 /** 564 * Checks that this method node is compatible with the given ASM API version. This method checks 565 * that this node, and all its children recursively, do not contain elements that were introduced 566 * in more recent versions of the ASM API than the given version. 567 * 568 * @param api an ASM API version. Must be one of the {@code ASM}<i>x</i> values in {@link 569 * Opcodes}. 570 */ 571 public void check(final int api) { 572 if (api == Opcodes.ASM4) { 573 if (parameters != null && !parameters.isEmpty()) { 574 throw new UnsupportedClassVersionException(); 575 } 576 if (visibleTypeAnnotations != null && !visibleTypeAnnotations.isEmpty()) { 577 throw new UnsupportedClassVersionException(); 578 } 579 if (invisibleTypeAnnotations != null && !invisibleTypeAnnotations.isEmpty()) { 580 throw new UnsupportedClassVersionException(); 581 } 582 if (tryCatchBlocks != null) { 583 for (int i = tryCatchBlocks.size() - 1; i >= 0; --i) { 584 TryCatchBlockNode tryCatchBlock = tryCatchBlocks.get(i); 585 if (tryCatchBlock.visibleTypeAnnotations != null 586 && !tryCatchBlock.visibleTypeAnnotations.isEmpty()) { 587 throw new UnsupportedClassVersionException(); 588 } 589 if (tryCatchBlock.invisibleTypeAnnotations != null 590 && !tryCatchBlock.invisibleTypeAnnotations.isEmpty()) { 591 throw new UnsupportedClassVersionException(); 592 } 593 } 594 } 595 for (int i = instructions.size() - 1; i >= 0; --i) { 596 AbstractInsnNode insn = instructions.get(i); 597 if (insn.visibleTypeAnnotations != null && !insn.visibleTypeAnnotations.isEmpty()) { 598 throw new UnsupportedClassVersionException(); 599 } 600 if (insn.invisibleTypeAnnotations != null && !insn.invisibleTypeAnnotations.isEmpty()) { 601 throw new UnsupportedClassVersionException(); 602 } 603 if (insn instanceof MethodInsnNode) { 604 boolean isInterface = ((MethodInsnNode) insn).itf; 605 if (isInterface != (insn.opcode == Opcodes.INVOKEINTERFACE)) { 606 throw new UnsupportedClassVersionException(); 607 } 608 } else if (insn instanceof LdcInsnNode) { 609 Object value = ((LdcInsnNode) insn).cst; 610 if (value instanceof Handle 611 || (value instanceof Type && ((Type) value).getSort() == Type.METHOD)) { 612 throw new UnsupportedClassVersionException(); 613 } 614 } 615 } 616 if (visibleLocalVariableAnnotations != null && !visibleLocalVariableAnnotations.isEmpty()) { 617 throw new UnsupportedClassVersionException(); 618 } 619 if (invisibleLocalVariableAnnotations != null 620 && !invisibleLocalVariableAnnotations.isEmpty()) { 621 throw new UnsupportedClassVersionException(); 622 } 623 } 624 if (api < Opcodes.ASM7) { 625 for (int i = instructions.size() - 1; i >= 0; --i) { 626 AbstractInsnNode insn = instructions.get(i); 627 if (insn instanceof LdcInsnNode) { 628 Object value = ((LdcInsnNode) insn).cst; 629 if (value instanceof ConstantDynamic) { 630 throw new UnsupportedClassVersionException(); 631 } 632 } 633 } 634 } 635 } 636 637 /** 638 * Makes the given class visitor visit this method. 639 * 640 * @param classVisitor a class visitor. 641 */ 642 public void accept(final ClassVisitor classVisitor) { 643 String[] exceptionsArray = exceptions == null ? null : exceptions.toArray(new String[0]); 644 MethodVisitor methodVisitor = 645 classVisitor.visitMethod(access, name, desc, signature, exceptionsArray); 646 if (methodVisitor != null) { 647 accept(methodVisitor); 648 } 649 } 650 651 /** 652 * Makes the given method visitor visit this method. 653 * 654 * @param methodVisitor a method visitor. 655 */ 656 public void accept(final MethodVisitor methodVisitor) { 657 // Visit the parameters. 658 if (parameters != null) { 659 for (int i = 0, n = parameters.size(); i < n; i++) { 660 parameters.get(i).accept(methodVisitor); 661 } 662 } 663 // Visit the annotations. 664 if (annotationDefault != null) { 665 AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault(); 666 AnnotationNode.accept(annotationVisitor, null, annotationDefault); 667 if (annotationVisitor != null) { 668 annotationVisitor.visitEnd(); 669 } 670 } 671 if (visibleAnnotations != null) { 672 for (int i = 0, n = visibleAnnotations.size(); i < n; ++i) { 673 AnnotationNode annotation = visibleAnnotations.get(i); 674 annotation.accept(methodVisitor.visitAnnotation(annotation.desc, true)); 675 } 676 } 677 if (invisibleAnnotations != null) { 678 for (int i = 0, n = invisibleAnnotations.size(); i < n; ++i) { 679 AnnotationNode annotation = invisibleAnnotations.get(i); 680 annotation.accept(methodVisitor.visitAnnotation(annotation.desc, false)); 681 } 682 } 683 if (visibleTypeAnnotations != null) { 684 for (int i = 0, n = visibleTypeAnnotations.size(); i < n; ++i) { 685 TypeAnnotationNode typeAnnotation = visibleTypeAnnotations.get(i); 686 typeAnnotation.accept( 687 methodVisitor.visitTypeAnnotation( 688 typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, true)); 689 } 690 } 691 if (invisibleTypeAnnotations != null) { 692 for (int i = 0, n = invisibleTypeAnnotations.size(); i < n; ++i) { 693 TypeAnnotationNode typeAnnotation = invisibleTypeAnnotations.get(i); 694 typeAnnotation.accept( 695 methodVisitor.visitTypeAnnotation( 696 typeAnnotation.typeRef, typeAnnotation.typePath, typeAnnotation.desc, false)); 697 } 698 } 699 if (visibleAnnotableParameterCount > 0) { 700 methodVisitor.visitAnnotableParameterCount(visibleAnnotableParameterCount, true); 701 } 702 if (visibleParameterAnnotations != null) { 703 for (int i = 0, n = visibleParameterAnnotations.length; i < n; ++i) { 704 List<AnnotationNode> parameterAnnotations = visibleParameterAnnotations[i]; 705 if (parameterAnnotations == null) { 706 continue; 707 } 708 for (int j = 0, m = parameterAnnotations.size(); j < m; ++j) { 709 AnnotationNode annotation = parameterAnnotations.get(j); 710 annotation.accept(methodVisitor.visitParameterAnnotation(i, annotation.desc, true)); 711 } 712 } 713 } 714 if (invisibleAnnotableParameterCount > 0) { 715 methodVisitor.visitAnnotableParameterCount(invisibleAnnotableParameterCount, false); 716 } 717 if (invisibleParameterAnnotations != null) { 718 for (int i = 0, n = invisibleParameterAnnotations.length; i < n; ++i) { 719 List<AnnotationNode> parameterAnnotations = invisibleParameterAnnotations[i]; 720 if (parameterAnnotations == null) { 721 continue; 722 } 723 for (int j = 0, m = parameterAnnotations.size(); j < m; ++j) { 724 AnnotationNode annotation = parameterAnnotations.get(j); 725 annotation.accept(methodVisitor.visitParameterAnnotation(i, annotation.desc, false)); 726 } 727 } 728 } 729 // Visit the non standard attributes. 730 if (visited) { 731 instructions.resetLabels(); 732 } 733 if (attrs != null) { 734 for (int i = 0, n = attrs.size(); i < n; ++i) { 735 methodVisitor.visitAttribute(attrs.get(i)); 736 } 737 } 738 // Visit the code. 739 if (instructions.size() > 0) { 740 methodVisitor.visitCode(); 741 // Visits the try catch blocks. 742 if (tryCatchBlocks != null) { 743 for (int i = 0, n = tryCatchBlocks.size(); i < n; ++i) { 744 tryCatchBlocks.get(i).updateIndex(i); 745 tryCatchBlocks.get(i).accept(methodVisitor); 746 } 747 } 748 // Visit the instructions. 749 instructions.accept(methodVisitor); 750 // Visits the local variables. 751 if (localVariables != null) { 752 for (int i = 0, n = localVariables.size(); i < n; ++i) { 753 localVariables.get(i).accept(methodVisitor); 754 } 755 } 756 // Visits the local variable annotations. 757 if (visibleLocalVariableAnnotations != null) { 758 for (int i = 0, n = visibleLocalVariableAnnotations.size(); i < n; ++i) { 759 visibleLocalVariableAnnotations.get(i).accept(methodVisitor, true); 760 } 761 } 762 if (invisibleLocalVariableAnnotations != null) { 763 for (int i = 0, n = invisibleLocalVariableAnnotations.size(); i < n; ++i) { 764 invisibleLocalVariableAnnotations.get(i).accept(methodVisitor, false); 765 } 766 } 767 methodVisitor.visitMaxs(maxStack, maxLocals); 768 visited = true; 769 } 770 methodVisitor.visitEnd(); 771 } 772 } 773