1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2011 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.sleepycat.asm; 31 32 /** 33 * A visitor to visit a Java method. The methods of this class must be 34 * called in the following order: [ <tt>visitAnnotationDefault</tt> ] ( 35 * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> | 36 * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> | 37 * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> | 38 * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] 39 * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt> 40 * and <tt>visitLabel</tt> methods must be called in the sequential order of 41 * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt> 42 * must be called <i>before</i> the labels passed as arguments have been 43 * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> 44 * methods must be called <i>after</i> the labels passed as arguments have been 45 * visited. 46 * 47 * @author Eric Bruneton 48 */ 49 public abstract class MethodVisitor { 50 51 /** 52 * The ASM API version implemented by this visitor. The value of this field 53 * must be one of {@link Opcodes#ASM4}. 54 */ 55 protected final int api; 56 57 /** 58 * The method visitor to which this visitor must delegate method calls. May 59 * be null. 60 */ 61 protected MethodVisitor mv; 62 63 /** 64 * Constructs a new {@link MethodVisitor}. 65 * 66 * @param api the ASM API version implemented by this visitor. Must be one 67 * of {@link Opcodes#ASM4}. 68 */ MethodVisitor(final int api)69 public MethodVisitor(final int api) { 70 this(api, null); 71 } 72 73 /** 74 * Constructs a new {@link MethodVisitor}. 75 * 76 * @param api the ASM API version implemented by this visitor. Must be one 77 * of {@link Opcodes#ASM4}. 78 * @param mv the method visitor to which this visitor must delegate method 79 * calls. May be null. 80 */ MethodVisitor(final int api, final MethodVisitor mv)81 public MethodVisitor(final int api, final MethodVisitor mv) { 82 /*if (api != Opcodes.ASM4) { 83 throw new IllegalArgumentException(); 84 }*/ 85 this.api = api; 86 this.mv = mv; 87 } 88 89 // ------------------------------------------------------------------------- 90 // Annotations and non standard attributes 91 // ------------------------------------------------------------------------- 92 93 /** 94 * Visits the default value of this annotation interface method. 95 * 96 * @return a visitor to the visit the actual default value of this 97 * annotation interface method, or <tt>null</tt> if this visitor 98 * is not interested in visiting this default value. The 'name' 99 * parameters passed to the methods of this annotation visitor are 100 * ignored. Moreover, exacly one visit method must be called on this 101 * annotation visitor, followed by visitEnd. 102 */ visitAnnotationDefault()103 public AnnotationVisitor visitAnnotationDefault() { 104 if (mv != null) { 105 return mv.visitAnnotationDefault(); 106 } 107 return null; 108 } 109 110 /** 111 * Visits an annotation of this method. 112 * 113 * @param desc the class descriptor of the annotation class. 114 * @param visible <tt>true</tt> if the annotation is visible at runtime. 115 * @return a visitor to visit the annotation values, or <tt>null</tt> if 116 * this visitor is not interested in visiting this annotation. 117 */ visitAnnotation(String desc, boolean visible)118 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 119 if (mv != null) { 120 return mv.visitAnnotation(desc, visible); 121 } 122 return null; 123 } 124 125 /** 126 * Visits an annotation of a parameter this method. 127 * 128 * @param parameter the parameter index. 129 * @param desc the class descriptor of the annotation class. 130 * @param visible <tt>true</tt> if the annotation is visible at runtime. 131 * @return a visitor to visit the annotation values, or <tt>null</tt> if 132 * this visitor is not interested in visiting this annotation. 133 */ visitParameterAnnotation( int parameter, String desc, boolean visible)134 public AnnotationVisitor visitParameterAnnotation( 135 int parameter, 136 String desc, 137 boolean visible) 138 { 139 if (mv != null) { 140 return mv.visitParameterAnnotation(parameter, desc, visible); 141 } 142 return null; 143 } 144 145 /** 146 * Visits a non standard attribute of this method. 147 * 148 * @param attr an attribute. 149 */ visitAttribute(Attribute attr)150 public void visitAttribute(Attribute attr) { 151 if (mv != null) { 152 mv.visitAttribute(attr); 153 } 154 } 155 156 /** 157 * Starts the visit of the method's code, if any (i.e. non abstract method). 158 */ visitCode()159 public void visitCode() { 160 if (mv != null) { 161 mv.visitCode(); 162 } 163 } 164 165 /** 166 * Visits the current state of the local variables and operand stack 167 * elements. This method must(*) be called <i>just before</i> any 168 * instruction <b>i</b> that follows an unconditional branch instruction 169 * such as GOTO or THROW, that is the target of a jump instruction, or that 170 * starts an exception handler block. The visited types must describe the 171 * values of the local variables and of the operand stack elements <i>just 172 * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only 173 * for classes whose version is greater than or equal to 174 * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically 175 * "deltas" from the state of the previous frame (very first frame is 176 * implicitly defined by the method's parameters and access flags): <ul> 177 * <li>{@link Opcodes#F_SAME} representing frame with exactly the same 178 * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1} 179 * representing frame with exactly the same locals as the previous frame and 180 * with single value on the stack (<code>nStack</code> is 1 and 181 * <code>stack[0]</code> contains value for the type of the stack item).</li> 182 * <li>{@link Opcodes#F_APPEND} representing frame with current locals are 183 * the same as the locals in the previous frame, except that additional 184 * locals are defined (<code>nLocal</code> is 1, 2 or 3 and 185 * <code>local</code> elements contains values representing added types).</li> 186 * <li>{@link Opcodes#F_CHOP} representing frame with current locals are 187 * the same as the locals in the previous frame, except that the last 1-3 188 * locals are absent and with the empty stack (<code>nLocals</code> is 1, 189 * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame 190 * data.</li> </li> </ul> 191 * 192 * @param type the type of this stack map frame. Must be 193 * {@link Opcodes#F_NEW} for expanded frames, or 194 * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, 195 * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or 196 * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed 197 * frames. 198 * @param nLocal the number of local variables in the visited frame. 199 * @param local the local variable types in this frame. This array must not 200 * be modified. Primitive types are represented by 201 * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, 202 * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, 203 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or 204 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are 205 * represented by a single element). Reference types are represented 206 * by String objects (representing internal names), and uninitialized 207 * types by Label objects (this label designates the NEW instruction 208 * that created this uninitialized value). 209 * @param nStack the number of operand stack elements in the visited frame. 210 * @param stack the operand stack types in this frame. This array must not 211 * be modified. Its content has the same format as the "local" array. 212 * @throws IllegalStateException if a frame is visited just after another 213 * one, without any instruction between the two (unless this frame 214 * is a Opcodes#F_SAME frame, in which case it is silently ignored). 215 */ visitFrame( int type, int nLocal, Object[] local, int nStack, Object[] stack)216 public void visitFrame( 217 int type, 218 int nLocal, 219 Object[] local, 220 int nStack, 221 Object[] stack) 222 { 223 if (mv != null) { 224 mv.visitFrame(type, nLocal, local, nStack, stack); 225 } 226 } 227 228 // ------------------------------------------------------------------------- 229 // Normal instructions 230 // ------------------------------------------------------------------------- 231 232 /** 233 * Visits a zero operand instruction. 234 * 235 * @param opcode the opcode of the instruction to be visited. This opcode is 236 * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, 237 * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, 238 * FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD, 239 * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, 240 * DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, 241 * DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD, 242 * DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, 243 * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, 244 * LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, 245 * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, 246 * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, 247 * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, 248 * MONITORENTER, or MONITOREXIT. 249 */ visitInsn(int opcode)250 public void visitInsn(int opcode) { 251 if (mv != null) { 252 mv.visitInsn(opcode); 253 } 254 } 255 256 /** 257 * Visits an instruction with a single int operand. 258 * 259 * @param opcode the opcode of the instruction to be visited. This opcode is 260 * either BIPUSH, SIPUSH or NEWARRAY. 261 * @param operand the operand of the instruction to be visited.<br> When 262 * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE 263 * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value 264 * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When 265 * opcode is NEWARRAY, operand value should be one of 266 * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, 267 * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, 268 * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, 269 * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. 270 */ visitIntInsn(int opcode, int operand)271 public void visitIntInsn(int opcode, int operand) { 272 if (mv != null) { 273 mv.visitIntInsn(opcode, operand); 274 } 275 } 276 277 /** 278 * Visits a local variable instruction. A local variable instruction is an 279 * instruction that loads or stores the value of a local variable. 280 * 281 * @param opcode the opcode of the local variable instruction to be visited. 282 * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, 283 * LSTORE, FSTORE, DSTORE, ASTORE or RET. 284 * @param var the operand of the instruction to be visited. This operand is 285 * the index of a local variable. 286 */ visitVarInsn(int opcode, int var)287 public void visitVarInsn(int opcode, int var) { 288 if (mv != null) { 289 mv.visitVarInsn(opcode, var); 290 } 291 } 292 293 /** 294 * Visits a type instruction. A type instruction is an instruction that 295 * takes the internal name of a class as parameter. 296 * 297 * @param opcode the opcode of the type instruction to be visited. This 298 * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. 299 * @param type the operand of the instruction to be visited. This operand 300 * must be the internal name of an object or array class (see {@link 301 * Type#getInternalName() getInternalName}). 302 */ visitTypeInsn(int opcode, String type)303 public void visitTypeInsn(int opcode, String type) { 304 if (mv != null) { 305 mv.visitTypeInsn(opcode, type); 306 } 307 } 308 309 /** 310 * Visits a field instruction. A field instruction is an instruction that 311 * loads or stores the value of a field of an object. 312 * 313 * @param opcode the opcode of the type instruction to be visited. This 314 * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. 315 * @param owner the internal name of the field's owner class (see {@link 316 * Type#getInternalName() getInternalName}). 317 * @param name the field's name. 318 * @param desc the field's descriptor (see {@link Type Type}). 319 */ visitFieldInsn(int opcode, String owner, String name, String desc)320 public void visitFieldInsn(int opcode, String owner, String name, String desc) { 321 if (mv != null) { 322 mv.visitFieldInsn(opcode, owner, name, desc); 323 } 324 } 325 326 /** 327 * Visits a method instruction. A method instruction is an instruction that 328 * invokes a method. 329 * 330 * @param opcode the opcode of the type instruction to be visited. This 331 * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC 332 * or INVOKEINTERFACE. 333 * @param owner the internal name of the method's owner class (see {@link 334 * Type#getInternalName() getInternalName}). 335 * @param name the method's name. 336 * @param desc the method's descriptor (see {@link Type Type}). 337 */ visitMethodInsn(int opcode, String owner, String name, String desc)338 public void visitMethodInsn(int opcode, String owner, String name, String desc) { 339 if (mv != null) { 340 mv.visitMethodInsn(opcode, owner, name, desc); 341 } 342 } 343 344 /** 345 * Visits an invokedynamic instruction. 346 * 347 * @param name the method's name. 348 * @param desc the method's descriptor (see {@link Type Type}). 349 * @param bsm the bootstrap method. 350 * @param bsmArgs the bootstrap method constant arguments. Each argument 351 * must be an {@link Integer}, {@link Float}, {@link Long}, 352 * {@link Double}, {@link String}, {@link Type} or {@link Handle} 353 * value. This method is allowed to modify the content of the array 354 * so a caller should expect that this array may change. 355 */ visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)356 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { 357 if (mv != null) { 358 mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); 359 } 360 } 361 362 /** 363 * Visits a jump instruction. A jump instruction is an instruction that may 364 * jump to another instruction. 365 * 366 * @param opcode the opcode of the type instruction to be visited. This 367 * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, 368 * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, 369 * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. 370 * @param label the operand of the instruction to be visited. This operand 371 * is a label that designates the instruction to which the jump 372 * instruction may jump. 373 */ visitJumpInsn(int opcode, Label label)374 public void visitJumpInsn(int opcode, Label label) { 375 if (mv != null) { 376 mv.visitJumpInsn(opcode, label); 377 } 378 } 379 380 /** 381 * Visits a label. A label designates the instruction that will be visited 382 * just after it. 383 * 384 * @param label a {@link Label Label} object. 385 */ visitLabel(Label label)386 public void visitLabel(Label label) { 387 if (mv != null) { 388 mv.visitLabel(label); 389 } 390 } 391 392 // ------------------------------------------------------------------------- 393 // Special instructions 394 // ------------------------------------------------------------------------- 395 396 /** 397 * Visits a LDC instruction. Note that new constant types may be added in 398 * future versions of the Java Virtual Machine. To easily detect new 399 * constant types, implementations of this method should check for 400 * unexpected constant types, like this: 401 * <pre> 402 * if (cst instanceof Integer) { 403 * // ... 404 * } else if (cst instanceof Float) { 405 * // ... 406 * } else if (cst instanceof Long) { 407 * // ... 408 * } else if (cst instanceof Double) { 409 * // ... 410 * } else if (cst instanceof String) { 411 * // ... 412 * } else if (cst instanceof Type) { 413 * int sort = ((Type) cst).getSort(); 414 * if (sort == Type.OBJECT) { 415 * // ... 416 * } else if (sort == Type.ARRAY) { 417 * // ... 418 * } else if (sort == Type.METHOD) { 419 * // ... 420 * } else { 421 * // throw an exception 422 * } 423 * } else if (cst instanceof Handle) { 424 * // ... 425 * } else { 426 * // throw an exception 427 * }</pre> 428 * 429 * @param cst the constant to be loaded on the stack. This parameter must be 430 * a non null {@link Integer}, a {@link Float}, a {@link Long}, a 431 * {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY 432 * sort for <tt>.class</tt> constants, for classes whose version is 433 * 49.0, a {@link Type} of METHOD sort or a {@link Handle} for 434 * MethodType and MethodHandle constants, for classes whose version 435 * is 51.0. 436 */ visitLdcInsn(Object cst)437 public void visitLdcInsn(Object cst) { 438 if (mv != null) { 439 mv.visitLdcInsn(cst); 440 } 441 } 442 443 /** 444 * Visits an IINC instruction. 445 * 446 * @param var index of the local variable to be incremented. 447 * @param increment amount to increment the local variable by. 448 */ visitIincInsn(int var, int increment)449 public void visitIincInsn(int var, int increment) { 450 if (mv != null) { 451 mv.visitIincInsn(var, increment); 452 } 453 } 454 455 /** 456 * Visits a TABLESWITCH instruction. 457 * 458 * @param min the minimum key value. 459 * @param max the maximum key value. 460 * @param dflt beginning of the default handler block. 461 * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is 462 * the beginning of the handler block for the <tt>min + i</tt> key. 463 */ visitTableSwitchInsn(int min, int max, Label dflt, Label... labels)464 public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { 465 if (mv != null) { 466 mv.visitTableSwitchInsn(min, max, dflt, labels); 467 } 468 } 469 470 /** 471 * Visits a LOOKUPSWITCH instruction. 472 * 473 * @param dflt beginning of the default handler block. 474 * @param keys the values of the keys. 475 * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is 476 * the beginning of the handler block for the <tt>keys[i]</tt> key. 477 */ visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels)478 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { 479 if (mv != null) { 480 mv.visitLookupSwitchInsn(dflt, keys, labels); 481 } 482 } 483 484 /** 485 * Visits a MULTIANEWARRAY instruction. 486 * 487 * @param desc an array type descriptor (see {@link Type Type}). 488 * @param dims number of dimensions of the array to allocate. 489 */ visitMultiANewArrayInsn(String desc, int dims)490 public void visitMultiANewArrayInsn(String desc, int dims) { 491 if (mv != null) { 492 mv.visitMultiANewArrayInsn(desc, dims); 493 } 494 } 495 496 // ------------------------------------------------------------------------- 497 // Exceptions table entries, debug information, max stack and max locals 498 // ------------------------------------------------------------------------- 499 500 /** 501 * Visits a try catch block. 502 * 503 * @param start beginning of the exception handler's scope (inclusive). 504 * @param end end of the exception handler's scope (exclusive). 505 * @param handler beginning of the exception handler's code. 506 * @param type internal name of the type of exceptions handled by the 507 * handler, or <tt>null</tt> to catch any exceptions (for "finally" 508 * blocks). 509 * @throws IllegalArgumentException if one of the labels has already been 510 * visited by this visitor (by the {@link #visitLabel visitLabel} 511 * method). 512 */ visitTryCatchBlock(Label start, Label end, Label handler, String type)513 public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 514 if (mv != null) { 515 mv.visitTryCatchBlock(start, end, handler, type); 516 } 517 } 518 519 /** 520 * Visits a local variable declaration. 521 * 522 * @param name the name of a local variable. 523 * @param desc the type descriptor of this local variable. 524 * @param signature the type signature of this local variable. May be 525 * <tt>null</tt> if the local variable type does not use generic 526 * types. 527 * @param start the first instruction corresponding to the scope of this 528 * local variable (inclusive). 529 * @param end the last instruction corresponding to the scope of this local 530 * variable (exclusive). 531 * @param index the local variable's index. 532 * @throws IllegalArgumentException if one of the labels has not already 533 * been visited by this visitor (by the 534 * {@link #visitLabel visitLabel} method). 535 */ visitLocalVariable( String name, String desc, String signature, Label start, Label end, int index)536 public void visitLocalVariable( 537 String name, 538 String desc, 539 String signature, 540 Label start, 541 Label end, 542 int index) 543 { 544 if (mv != null) { 545 mv.visitLocalVariable(name, desc, signature, start, end, index); 546 } 547 } 548 549 /** 550 * Visits a line number declaration. 551 * 552 * @param line a line number. This number refers to the source file from 553 * which the class was compiled. 554 * @param start the first instruction corresponding to this line number. 555 * @throws IllegalArgumentException if <tt>start</tt> has not already been 556 * visited by this visitor (by the {@link #visitLabel visitLabel} 557 * method). 558 */ visitLineNumber(int line, Label start)559 public void visitLineNumber(int line, Label start) { 560 if (mv != null) { 561 mv.visitLineNumber(line, start); 562 } 563 } 564 565 /** 566 * Visits the maximum stack size and the maximum number of local variables 567 * of the method. 568 * 569 * @param maxStack maximum stack size of the method. 570 * @param maxLocals maximum number of local variables for the method. 571 */ visitMaxs(int maxStack, int maxLocals)572 public void visitMaxs(int maxStack, int maxLocals) { 573 if (mv != null) { 574 mv.visitMaxs(maxStack, maxLocals); 575 } 576 } 577 578 /** 579 * Visits the end of the method. This method, which is the last one to be 580 * called, is used to inform the visitor that all the annotations and 581 * attributes of the method have been visited. 582 */ visitEnd()583 public void visitEnd() { 584 if (mv != null) { 585 mv.visitEnd(); 586 } 587 } 588 } 589