1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm.util; 60 61 import java.io.FileInputStream; 62 import java.io.PrintWriter; 63 import java.util.HashMap; 64 import java.util.Map; 65 66 import jdk.internal.org.objectweb.asm.Attribute; 67 import jdk.internal.org.objectweb.asm.ClassReader; 68 import jdk.internal.org.objectweb.asm.Handle; 69 import jdk.internal.org.objectweb.asm.Label; 70 import jdk.internal.org.objectweb.asm.Opcodes; 71 import jdk.internal.org.objectweb.asm.Type; 72 import jdk.internal.org.objectweb.asm.TypePath; 73 import jdk.internal.org.objectweb.asm.TypeReference; 74 import jdk.internal.org.objectweb.asm.signature.SignatureReader; 75 76 /** 77 * A {@link Printer} that prints a disassembled view of the classes it visits. 78 * 79 * @author Eric Bruneton 80 */ 81 public class Textifier extends Printer { 82 83 /** 84 * Constant used in {@link #appendDescriptor appendDescriptor} for internal 85 * type names in bytecode notation. 86 */ 87 public static final int INTERNAL_NAME = 0; 88 89 /** 90 * Constant used in {@link #appendDescriptor appendDescriptor} for field 91 * descriptors, formatted in bytecode notation 92 */ 93 public static final int FIELD_DESCRIPTOR = 1; 94 95 /** 96 * Constant used in {@link #appendDescriptor appendDescriptor} for field 97 * signatures, formatted in bytecode notation 98 */ 99 public static final int FIELD_SIGNATURE = 2; 100 101 /** 102 * Constant used in {@link #appendDescriptor appendDescriptor} for method 103 * descriptors, formatted in bytecode notation 104 */ 105 public static final int METHOD_DESCRIPTOR = 3; 106 107 /** 108 * Constant used in {@link #appendDescriptor appendDescriptor} for method 109 * signatures, formatted in bytecode notation 110 */ 111 public static final int METHOD_SIGNATURE = 4; 112 113 /** 114 * Constant used in {@link #appendDescriptor appendDescriptor} for class 115 * signatures, formatted in bytecode notation 116 */ 117 public static final int CLASS_SIGNATURE = 5; 118 119 /** 120 * Constant used in {@link #appendDescriptor appendDescriptor} for field or 121 * method return value signatures, formatted in default Java notation 122 * (non-bytecode) 123 */ 124 public static final int TYPE_DECLARATION = 6; 125 126 /** 127 * Constant used in {@link #appendDescriptor appendDescriptor} for class 128 * signatures, formatted in default Java notation (non-bytecode) 129 */ 130 public static final int CLASS_DECLARATION = 7; 131 132 /** 133 * Constant used in {@link #appendDescriptor appendDescriptor} for method 134 * parameter signatures, formatted in default Java notation (non-bytecode) 135 */ 136 public static final int PARAMETERS_DECLARATION = 8; 137 138 /** 139 * Constant used in {@link #appendDescriptor appendDescriptor} for handle 140 * descriptors, formatted in bytecode notation 141 */ 142 public static final int HANDLE_DESCRIPTOR = 9; 143 144 /** 145 * Tab for class members. 146 */ 147 protected String tab = " "; 148 149 /** 150 * Tab for bytecode instructions. 151 */ 152 protected String tab2 = " "; 153 154 /** 155 * Tab for table and lookup switch instructions. 156 */ 157 protected String tab3 = " "; 158 159 /** 160 * Tab for labels. 161 */ 162 protected String ltab = " "; 163 164 /** 165 * The label names. This map associate String values to Label keys. 166 */ 167 protected Map<Label, String> labelNames; 168 169 /** 170 * Class access flags 171 */ 172 private int access; 173 174 private int valueNumber = 0; 175 176 /** 177 * Constructs a new {@link Textifier}. <i>Subclasses must not use this 178 * constructor</i>. Instead, they must use the {@link #Textifier(int)} 179 * version. 180 * 181 * @throws IllegalStateException 182 * If a subclass calls this constructor. 183 */ Textifier()184 public Textifier() { 185 this(Opcodes.ASM5); 186 if (getClass() != Textifier.class) { 187 throw new IllegalStateException(); 188 } 189 } 190 191 /** 192 * Constructs a new {@link Textifier}. 193 * 194 * @param api 195 * the ASM API version implemented by this visitor. Must be one 196 * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. 197 */ Textifier(final int api)198 protected Textifier(final int api) { 199 super(api); 200 } 201 202 /** 203 * Prints a disassembled view of the given class to the standard output. 204 * <p> 205 * Usage: Textifier [-debug] <binary class name or class file name > 206 * 207 * @param args 208 * the command line arguments. 209 * 210 * @throws Exception 211 * if the class cannot be found, or if an IO exception occurs. 212 */ main(final String[] args)213 public static void main(final String[] args) throws Exception { 214 int i = 0; 215 int flags = ClassReader.SKIP_DEBUG; 216 217 boolean ok = true; 218 if (args.length < 1 || args.length > 2) { 219 ok = false; 220 } 221 if (ok && "-debug".equals(args[0])) { 222 i = 1; 223 flags = 0; 224 if (args.length != 2) { 225 ok = false; 226 } 227 } 228 if (!ok) { 229 System.err 230 .println("Prints a disassembled view of the given class."); 231 System.err.println("Usage: Textifier [-debug] " 232 + "<fully qualified class name or class file name>"); 233 return; 234 } 235 ClassReader cr; 236 if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 237 || args[i].indexOf('/') > -1) { 238 cr = new ClassReader(new FileInputStream(args[i])); 239 } else { 240 cr = new ClassReader(args[i]); 241 } 242 cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags); 243 } 244 245 // ------------------------------------------------------------------------ 246 // Classes 247 // ------------------------------------------------------------------------ 248 249 @Override visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)250 public void visit(final int version, final int access, final String name, 251 final String signature, final String superName, 252 final String[] interfaces) { 253 this.access = access; 254 int major = version & 0xFFFF; 255 int minor = version >>> 16; 256 buf.setLength(0); 257 buf.append("// class version ").append(major).append('.').append(minor) 258 .append(" (").append(version).append(")\n"); 259 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 260 buf.append("// DEPRECATED\n"); 261 } 262 buf.append("// access flags 0x") 263 .append(Integer.toHexString(access).toUpperCase()).append('\n'); 264 265 appendDescriptor(CLASS_SIGNATURE, signature); 266 if (signature != null) { 267 TraceSignatureVisitor sv = new TraceSignatureVisitor(access); 268 SignatureReader r = new SignatureReader(signature); 269 r.accept(sv); 270 buf.append("// declaration: ").append(name) 271 .append(sv.getDeclaration()).append('\n'); 272 } 273 274 appendAccess(access & ~Opcodes.ACC_SUPER); 275 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 276 buf.append("@interface "); 277 } else if ((access & Opcodes.ACC_INTERFACE) != 0) { 278 buf.append("interface "); 279 } else if ((access & Opcodes.ACC_ENUM) == 0) { 280 buf.append("class "); 281 } 282 appendDescriptor(INTERNAL_NAME, name); 283 284 if (superName != null && !"java/lang/Object".equals(superName)) { 285 buf.append(" extends "); 286 appendDescriptor(INTERNAL_NAME, superName); 287 buf.append(' '); 288 } 289 if (interfaces != null && interfaces.length > 0) { 290 buf.append(" implements "); 291 for (int i = 0; i < interfaces.length; ++i) { 292 appendDescriptor(INTERNAL_NAME, interfaces[i]); 293 buf.append(' '); 294 } 295 } 296 buf.append(" {\n\n"); 297 298 text.add(buf.toString()); 299 } 300 301 @Override visitSource(final String file, final String debug)302 public void visitSource(final String file, final String debug) { 303 buf.setLength(0); 304 if (file != null) { 305 buf.append(tab).append("// compiled from: ").append(file) 306 .append('\n'); 307 } 308 if (debug != null) { 309 buf.append(tab).append("// debug info: ").append(debug) 310 .append('\n'); 311 } 312 if (buf.length() > 0) { 313 text.add(buf.toString()); 314 } 315 } 316 317 @Override visitOuterClass(final String owner, final String name, final String desc)318 public void visitOuterClass(final String owner, final String name, 319 final String desc) { 320 buf.setLength(0); 321 buf.append(tab).append("OUTERCLASS "); 322 appendDescriptor(INTERNAL_NAME, owner); 323 buf.append(' '); 324 if (name != null) { 325 buf.append(name).append(' '); 326 } 327 appendDescriptor(METHOD_DESCRIPTOR, desc); 328 buf.append('\n'); 329 text.add(buf.toString()); 330 } 331 332 @Override visitClassAnnotation(final String desc, final boolean visible)333 public Textifier visitClassAnnotation(final String desc, 334 final boolean visible) { 335 text.add("\n"); 336 return visitAnnotation(desc, visible); 337 } 338 339 @Override visitClassTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible)340 public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath, 341 String desc, boolean visible) { 342 text.add("\n"); 343 return visitTypeAnnotation(typeRef, typePath, desc, visible); 344 } 345 346 @Override visitClassAttribute(final Attribute attr)347 public void visitClassAttribute(final Attribute attr) { 348 text.add("\n"); 349 visitAttribute(attr); 350 } 351 352 @Override visitInnerClass(final String name, final String outerName, final String innerName, final int access)353 public void visitInnerClass(final String name, final String outerName, 354 final String innerName, final int access) { 355 buf.setLength(0); 356 buf.append(tab).append("// access flags 0x"); 357 buf.append( 358 Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()) 359 .append('\n'); 360 buf.append(tab); 361 appendAccess(access); 362 buf.append("INNERCLASS "); 363 appendDescriptor(INTERNAL_NAME, name); 364 buf.append(' '); 365 appendDescriptor(INTERNAL_NAME, outerName); 366 buf.append(' '); 367 appendDescriptor(INTERNAL_NAME, innerName); 368 buf.append('\n'); 369 text.add(buf.toString()); 370 } 371 372 @Override visitField(final int access, final String name, final String desc, final String signature, final Object value)373 public Textifier visitField(final int access, final String name, 374 final String desc, final String signature, final Object value) { 375 buf.setLength(0); 376 buf.append('\n'); 377 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 378 buf.append(tab).append("// DEPRECATED\n"); 379 } 380 buf.append(tab).append("// access flags 0x") 381 .append(Integer.toHexString(access).toUpperCase()).append('\n'); 382 if (signature != null) { 383 buf.append(tab); 384 appendDescriptor(FIELD_SIGNATURE, signature); 385 386 TraceSignatureVisitor sv = new TraceSignatureVisitor(0); 387 SignatureReader r = new SignatureReader(signature); 388 r.acceptType(sv); 389 buf.append(tab).append("// declaration: ") 390 .append(sv.getDeclaration()).append('\n'); 391 } 392 393 buf.append(tab); 394 appendAccess(access); 395 396 appendDescriptor(FIELD_DESCRIPTOR, desc); 397 buf.append(' ').append(name); 398 if (value != null) { 399 buf.append(" = "); 400 if (value instanceof String) { 401 buf.append('\"').append(value).append('\"'); 402 } else { 403 buf.append(value); 404 } 405 } 406 407 buf.append('\n'); 408 text.add(buf.toString()); 409 410 Textifier t = createTextifier(); 411 text.add(t.getText()); 412 return t; 413 } 414 415 @Override visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions)416 public Textifier visitMethod(final int access, final String name, 417 final String desc, final String signature, final String[] exceptions) { 418 buf.setLength(0); 419 buf.append('\n'); 420 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 421 buf.append(tab).append("// DEPRECATED\n"); 422 } 423 buf.append(tab).append("// access flags 0x") 424 .append(Integer.toHexString(access).toUpperCase()).append('\n'); 425 426 if (signature != null) { 427 buf.append(tab); 428 appendDescriptor(METHOD_SIGNATURE, signature); 429 430 TraceSignatureVisitor v = new TraceSignatureVisitor(0); 431 SignatureReader r = new SignatureReader(signature); 432 r.accept(v); 433 String genericDecl = v.getDeclaration(); 434 String genericReturn = v.getReturnType(); 435 String genericExceptions = v.getExceptions(); 436 437 buf.append(tab).append("// declaration: ").append(genericReturn) 438 .append(' ').append(name).append(genericDecl); 439 if (genericExceptions != null) { 440 buf.append(" throws ").append(genericExceptions); 441 } 442 buf.append('\n'); 443 } 444 445 buf.append(tab); 446 appendAccess(access & ~Opcodes.ACC_VOLATILE); 447 if ((access & Opcodes.ACC_NATIVE) != 0) { 448 buf.append("native "); 449 } 450 if ((access & Opcodes.ACC_VARARGS) != 0) { 451 buf.append("varargs "); 452 } 453 if ((access & Opcodes.ACC_BRIDGE) != 0) { 454 buf.append("bridge "); 455 } 456 if ((this.access & Opcodes.ACC_INTERFACE) != 0 457 && (access & Opcodes.ACC_ABSTRACT) == 0 458 && (access & Opcodes.ACC_STATIC) == 0) { 459 buf.append("default "); 460 } 461 462 buf.append(name); 463 appendDescriptor(METHOD_DESCRIPTOR, desc); 464 if (exceptions != null && exceptions.length > 0) { 465 buf.append(" throws "); 466 for (int i = 0; i < exceptions.length; ++i) { 467 appendDescriptor(INTERNAL_NAME, exceptions[i]); 468 buf.append(' '); 469 } 470 } 471 472 buf.append('\n'); 473 text.add(buf.toString()); 474 475 Textifier t = createTextifier(); 476 text.add(t.getText()); 477 return t; 478 } 479 480 @Override visitClassEnd()481 public void visitClassEnd() { 482 text.add("}\n"); 483 } 484 485 // ------------------------------------------------------------------------ 486 // Annotations 487 // ------------------------------------------------------------------------ 488 489 @Override visit(final String name, final Object value)490 public void visit(final String name, final Object value) { 491 buf.setLength(0); 492 appendComa(valueNumber++); 493 494 if (name != null) { 495 buf.append(name).append('='); 496 } 497 498 if (value instanceof String) { 499 visitString((String) value); 500 } else if (value instanceof Type) { 501 visitType((Type) value); 502 } else if (value instanceof Byte) { 503 visitByte(((Byte) value).byteValue()); 504 } else if (value instanceof Boolean) { 505 visitBoolean(((Boolean) value).booleanValue()); 506 } else if (value instanceof Short) { 507 visitShort(((Short) value).shortValue()); 508 } else if (value instanceof Character) { 509 visitChar(((Character) value).charValue()); 510 } else if (value instanceof Integer) { 511 visitInt(((Integer) value).intValue()); 512 } else if (value instanceof Float) { 513 visitFloat(((Float) value).floatValue()); 514 } else if (value instanceof Long) { 515 visitLong(((Long) value).longValue()); 516 } else if (value instanceof Double) { 517 visitDouble(((Double) value).doubleValue()); 518 } else if (value.getClass().isArray()) { 519 buf.append('{'); 520 if (value instanceof byte[]) { 521 byte[] v = (byte[]) value; 522 for (int i = 0; i < v.length; i++) { 523 appendComa(i); 524 visitByte(v[i]); 525 } 526 } else if (value instanceof boolean[]) { 527 boolean[] v = (boolean[]) value; 528 for (int i = 0; i < v.length; i++) { 529 appendComa(i); 530 visitBoolean(v[i]); 531 } 532 } else if (value instanceof short[]) { 533 short[] v = (short[]) value; 534 for (int i = 0; i < v.length; i++) { 535 appendComa(i); 536 visitShort(v[i]); 537 } 538 } else if (value instanceof char[]) { 539 char[] v = (char[]) value; 540 for (int i = 0; i < v.length; i++) { 541 appendComa(i); 542 visitChar(v[i]); 543 } 544 } else if (value instanceof int[]) { 545 int[] v = (int[]) value; 546 for (int i = 0; i < v.length; i++) { 547 appendComa(i); 548 visitInt(v[i]); 549 } 550 } else if (value instanceof long[]) { 551 long[] v = (long[]) value; 552 for (int i = 0; i < v.length; i++) { 553 appendComa(i); 554 visitLong(v[i]); 555 } 556 } else if (value instanceof float[]) { 557 float[] v = (float[]) value; 558 for (int i = 0; i < v.length; i++) { 559 appendComa(i); 560 visitFloat(v[i]); 561 } 562 } else if (value instanceof double[]) { 563 double[] v = (double[]) value; 564 for (int i = 0; i < v.length; i++) { 565 appendComa(i); 566 visitDouble(v[i]); 567 } 568 } 569 buf.append('}'); 570 } 571 572 text.add(buf.toString()); 573 } 574 visitInt(final int value)575 private void visitInt(final int value) { 576 buf.append(value); 577 } 578 visitLong(final long value)579 private void visitLong(final long value) { 580 buf.append(value).append('L'); 581 } 582 visitFloat(final float value)583 private void visitFloat(final float value) { 584 buf.append(value).append('F'); 585 } 586 visitDouble(final double value)587 private void visitDouble(final double value) { 588 buf.append(value).append('D'); 589 } 590 visitChar(final char value)591 private void visitChar(final char value) { 592 buf.append("(char)").append((int) value); 593 } 594 visitShort(final short value)595 private void visitShort(final short value) { 596 buf.append("(short)").append(value); 597 } 598 visitByte(final byte value)599 private void visitByte(final byte value) { 600 buf.append("(byte)").append(value); 601 } 602 visitBoolean(final boolean value)603 private void visitBoolean(final boolean value) { 604 buf.append(value); 605 } 606 visitString(final String value)607 private void visitString(final String value) { 608 appendString(buf, value); 609 } 610 visitType(final Type value)611 private void visitType(final Type value) { 612 buf.append(value.getClassName()).append(".class"); 613 } 614 615 @Override visitEnum(final String name, final String desc, final String value)616 public void visitEnum(final String name, final String desc, 617 final String value) { 618 buf.setLength(0); 619 appendComa(valueNumber++); 620 if (name != null) { 621 buf.append(name).append('='); 622 } 623 appendDescriptor(FIELD_DESCRIPTOR, desc); 624 buf.append('.').append(value); 625 text.add(buf.toString()); 626 } 627 628 @Override visitAnnotation(final String name, final String desc)629 public Textifier visitAnnotation(final String name, final String desc) { 630 buf.setLength(0); 631 appendComa(valueNumber++); 632 if (name != null) { 633 buf.append(name).append('='); 634 } 635 buf.append('@'); 636 appendDescriptor(FIELD_DESCRIPTOR, desc); 637 buf.append('('); 638 text.add(buf.toString()); 639 Textifier t = createTextifier(); 640 text.add(t.getText()); 641 text.add(")"); 642 return t; 643 } 644 645 @Override visitArray(final String name)646 public Textifier visitArray(final String name) { 647 buf.setLength(0); 648 appendComa(valueNumber++); 649 if (name != null) { 650 buf.append(name).append('='); 651 } 652 buf.append('{'); 653 text.add(buf.toString()); 654 Textifier t = createTextifier(); 655 text.add(t.getText()); 656 text.add("}"); 657 return t; 658 } 659 660 @Override visitAnnotationEnd()661 public void visitAnnotationEnd() { 662 } 663 664 // ------------------------------------------------------------------------ 665 // Fields 666 // ------------------------------------------------------------------------ 667 668 @Override visitFieldAnnotation(final String desc, final boolean visible)669 public Textifier visitFieldAnnotation(final String desc, 670 final boolean visible) { 671 return visitAnnotation(desc, visible); 672 } 673 674 @Override visitFieldTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible)675 public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath, 676 String desc, boolean visible) { 677 return visitTypeAnnotation(typeRef, typePath, desc, visible); 678 } 679 680 @Override visitFieldAttribute(final Attribute attr)681 public void visitFieldAttribute(final Attribute attr) { 682 visitAttribute(attr); 683 } 684 685 @Override visitFieldEnd()686 public void visitFieldEnd() { 687 } 688 689 // ------------------------------------------------------------------------ 690 // Methods 691 // ------------------------------------------------------------------------ 692 693 @Override visitParameter(final String name, final int access)694 public void visitParameter(final String name, final int access) { 695 buf.setLength(0); 696 buf.append(tab2).append("// parameter "); 697 appendAccess(access); 698 buf.append(' ').append((name == null) ? "<no name>" : name) 699 .append('\n'); 700 text.add(buf.toString()); 701 } 702 703 @Override visitAnnotationDefault()704 public Textifier visitAnnotationDefault() { 705 text.add(tab2 + "default="); 706 Textifier t = createTextifier(); 707 text.add(t.getText()); 708 text.add("\n"); 709 return t; 710 } 711 712 @Override visitMethodAnnotation(final String desc, final boolean visible)713 public Textifier visitMethodAnnotation(final String desc, 714 final boolean visible) { 715 return visitAnnotation(desc, visible); 716 } 717 718 @Override visitMethodTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible)719 public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath, 720 String desc, boolean visible) { 721 return visitTypeAnnotation(typeRef, typePath, desc, visible); 722 } 723 724 @Override visitParameterAnnotation(final int parameter, final String desc, final boolean visible)725 public Textifier visitParameterAnnotation(final int parameter, 726 final String desc, final boolean visible) { 727 buf.setLength(0); 728 buf.append(tab2).append('@'); 729 appendDescriptor(FIELD_DESCRIPTOR, desc); 730 buf.append('('); 731 text.add(buf.toString()); 732 Textifier t = createTextifier(); 733 text.add(t.getText()); 734 text.add(visible ? ") // parameter " : ") // invisible, parameter "); 735 text.add(parameter); 736 text.add("\n"); 737 return t; 738 } 739 740 @Override visitMethodAttribute(final Attribute attr)741 public void visitMethodAttribute(final Attribute attr) { 742 buf.setLength(0); 743 buf.append(tab).append("ATTRIBUTE "); 744 appendDescriptor(-1, attr.type); 745 746 if (attr instanceof Textifiable) { 747 ((Textifiable) attr).textify(buf, labelNames); 748 } else { 749 buf.append(" : unknown\n"); 750 } 751 752 text.add(buf.toString()); 753 } 754 755 @Override visitCode()756 public void visitCode() { 757 } 758 759 @Override visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack)760 public void visitFrame(final int type, final int nLocal, 761 final Object[] local, final int nStack, final Object[] stack) { 762 buf.setLength(0); 763 buf.append(ltab); 764 buf.append("FRAME "); 765 switch (type) { 766 case Opcodes.F_NEW: 767 case Opcodes.F_FULL: 768 buf.append("FULL ["); 769 appendFrameTypes(nLocal, local); 770 buf.append("] ["); 771 appendFrameTypes(nStack, stack); 772 buf.append(']'); 773 break; 774 case Opcodes.F_APPEND: 775 buf.append("APPEND ["); 776 appendFrameTypes(nLocal, local); 777 buf.append(']'); 778 break; 779 case Opcodes.F_CHOP: 780 buf.append("CHOP ").append(nLocal); 781 break; 782 case Opcodes.F_SAME: 783 buf.append("SAME"); 784 break; 785 case Opcodes.F_SAME1: 786 buf.append("SAME1 "); 787 appendFrameTypes(1, stack); 788 break; 789 } 790 buf.append('\n'); 791 text.add(buf.toString()); 792 } 793 794 @Override visitInsn(final int opcode)795 public void visitInsn(final int opcode) { 796 buf.setLength(0); 797 buf.append(tab2).append(OPCODES[opcode]).append('\n'); 798 text.add(buf.toString()); 799 } 800 801 @Override visitIntInsn(final int opcode, final int operand)802 public void visitIntInsn(final int opcode, final int operand) { 803 buf.setLength(0); 804 buf.append(tab2) 805 .append(OPCODES[opcode]) 806 .append(' ') 807 .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer 808 .toString(operand)).append('\n'); 809 text.add(buf.toString()); 810 } 811 812 @Override visitVarInsn(final int opcode, final int var)813 public void visitVarInsn(final int opcode, final int var) { 814 buf.setLength(0); 815 buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var) 816 .append('\n'); 817 text.add(buf.toString()); 818 } 819 820 @Override visitTypeInsn(final int opcode, final String type)821 public void visitTypeInsn(final int opcode, final String type) { 822 buf.setLength(0); 823 buf.append(tab2).append(OPCODES[opcode]).append(' '); 824 appendDescriptor(INTERNAL_NAME, type); 825 buf.append('\n'); 826 text.add(buf.toString()); 827 } 828 829 @Override visitFieldInsn(final int opcode, final String owner, final String name, final String desc)830 public void visitFieldInsn(final int opcode, final String owner, 831 final String name, final String desc) { 832 buf.setLength(0); 833 buf.append(tab2).append(OPCODES[opcode]).append(' '); 834 appendDescriptor(INTERNAL_NAME, owner); 835 buf.append('.').append(name).append(" : "); 836 appendDescriptor(FIELD_DESCRIPTOR, desc); 837 buf.append('\n'); 838 text.add(buf.toString()); 839 } 840 841 @Deprecated 842 @Override visitMethodInsn(final int opcode, final String owner, final String name, final String desc)843 public void visitMethodInsn(final int opcode, final String owner, 844 final String name, final String desc) { 845 if (api >= Opcodes.ASM5) { 846 super.visitMethodInsn(opcode, owner, name, desc); 847 return; 848 } 849 doVisitMethodInsn(opcode, owner, name, desc, 850 opcode == Opcodes.INVOKEINTERFACE); 851 } 852 853 @Override visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf)854 public void visitMethodInsn(final int opcode, final String owner, 855 final String name, final String desc, final boolean itf) { 856 if (api < Opcodes.ASM5) { 857 super.visitMethodInsn(opcode, owner, name, desc, itf); 858 return; 859 } 860 doVisitMethodInsn(opcode, owner, name, desc, itf); 861 } 862 doVisitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf)863 private void doVisitMethodInsn(final int opcode, final String owner, 864 final String name, final String desc, final boolean itf) { 865 buf.setLength(0); 866 buf.append(tab2).append(OPCODES[opcode]).append(' '); 867 appendDescriptor(INTERNAL_NAME, owner); 868 buf.append('.').append(name).append(' '); 869 appendDescriptor(METHOD_DESCRIPTOR, desc); 870 buf.append('\n'); 871 text.add(buf.toString()); 872 } 873 874 @Override visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)875 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 876 Object... bsmArgs) { 877 buf.setLength(0); 878 buf.append(tab2).append("INVOKEDYNAMIC").append(' '); 879 buf.append(name); 880 appendDescriptor(METHOD_DESCRIPTOR, desc); 881 buf.append(" ["); 882 buf.append('\n'); 883 buf.append(tab3); 884 appendHandle(bsm); 885 buf.append('\n'); 886 buf.append(tab3).append("// arguments:"); 887 if (bsmArgs.length == 0) { 888 buf.append(" none"); 889 } else { 890 buf.append('\n'); 891 for (int i = 0; i < bsmArgs.length; i++) { 892 buf.append(tab3); 893 Object cst = bsmArgs[i]; 894 if (cst instanceof String) { 895 Printer.appendString(buf, (String) cst); 896 } else if (cst instanceof Type) { 897 Type type = (Type) cst; 898 if(type.getSort() == Type.METHOD){ 899 appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor()); 900 } else { 901 buf.append(type.getDescriptor()).append(".class"); 902 } 903 } else if (cst instanceof Handle) { 904 appendHandle((Handle) cst); 905 } else { 906 buf.append(cst); 907 } 908 buf.append(", \n"); 909 } 910 buf.setLength(buf.length() - 3); 911 } 912 buf.append('\n'); 913 buf.append(tab2).append("]\n"); 914 text.add(buf.toString()); 915 } 916 917 @Override visitJumpInsn(final int opcode, final Label label)918 public void visitJumpInsn(final int opcode, final Label label) { 919 buf.setLength(0); 920 buf.append(tab2).append(OPCODES[opcode]).append(' '); 921 appendLabel(label); 922 buf.append('\n'); 923 text.add(buf.toString()); 924 } 925 926 @Override visitLabel(final Label label)927 public void visitLabel(final Label label) { 928 buf.setLength(0); 929 buf.append(ltab); 930 appendLabel(label); 931 buf.append('\n'); 932 text.add(buf.toString()); 933 } 934 935 @Override visitLdcInsn(final Object cst)936 public void visitLdcInsn(final Object cst) { 937 buf.setLength(0); 938 buf.append(tab2).append("LDC "); 939 if (cst instanceof String) { 940 Printer.appendString(buf, (String) cst); 941 } else if (cst instanceof Type) { 942 buf.append(((Type) cst).getDescriptor()).append(".class"); 943 } else { 944 buf.append(cst); 945 } 946 buf.append('\n'); 947 text.add(buf.toString()); 948 } 949 950 @Override visitIincInsn(final int var, final int increment)951 public void visitIincInsn(final int var, final int increment) { 952 buf.setLength(0); 953 buf.append(tab2).append("IINC ").append(var).append(' ') 954 .append(increment).append('\n'); 955 text.add(buf.toString()); 956 } 957 958 @Override visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels)959 public void visitTableSwitchInsn(final int min, final int max, 960 final Label dflt, final Label... labels) { 961 buf.setLength(0); 962 buf.append(tab2).append("TABLESWITCH\n"); 963 for (int i = 0; i < labels.length; ++i) { 964 buf.append(tab3).append(min + i).append(": "); 965 appendLabel(labels[i]); 966 buf.append('\n'); 967 } 968 buf.append(tab3).append("default: "); 969 appendLabel(dflt); 970 buf.append('\n'); 971 text.add(buf.toString()); 972 } 973 974 @Override visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)975 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, 976 final Label[] labels) { 977 buf.setLength(0); 978 buf.append(tab2).append("LOOKUPSWITCH\n"); 979 for (int i = 0; i < labels.length; ++i) { 980 buf.append(tab3).append(keys[i]).append(": "); 981 appendLabel(labels[i]); 982 buf.append('\n'); 983 } 984 buf.append(tab3).append("default: "); 985 appendLabel(dflt); 986 buf.append('\n'); 987 text.add(buf.toString()); 988 } 989 990 @Override visitMultiANewArrayInsn(final String desc, final int dims)991 public void visitMultiANewArrayInsn(final String desc, final int dims) { 992 buf.setLength(0); 993 buf.append(tab2).append("MULTIANEWARRAY "); 994 appendDescriptor(FIELD_DESCRIPTOR, desc); 995 buf.append(' ').append(dims).append('\n'); 996 text.add(buf.toString()); 997 } 998 999 @Override visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible)1000 public Printer visitInsnAnnotation(int typeRef, TypePath typePath, 1001 String desc, boolean visible) { 1002 return visitTypeAnnotation(typeRef, typePath, desc, visible); 1003 } 1004 1005 @Override visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type)1006 public void visitTryCatchBlock(final Label start, final Label end, 1007 final Label handler, final String type) { 1008 buf.setLength(0); 1009 buf.append(tab2).append("TRYCATCHBLOCK "); 1010 appendLabel(start); 1011 buf.append(' '); 1012 appendLabel(end); 1013 buf.append(' '); 1014 appendLabel(handler); 1015 buf.append(' '); 1016 appendDescriptor(INTERNAL_NAME, type); 1017 buf.append('\n'); 1018 text.add(buf.toString()); 1019 } 1020 1021 @Override visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible)1022 public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath, 1023 String desc, boolean visible) { 1024 buf.setLength(0); 1025 buf.append(tab2).append("TRYCATCHBLOCK @"); 1026 appendDescriptor(FIELD_DESCRIPTOR, desc); 1027 buf.append('('); 1028 text.add(buf.toString()); 1029 Textifier t = createTextifier(); 1030 text.add(t.getText()); 1031 buf.setLength(0); 1032 buf.append(") : "); 1033 appendTypeReference(typeRef); 1034 buf.append(", ").append(typePath); 1035 buf.append(visible ? "\n" : " // invisible\n"); 1036 text.add(buf.toString()); 1037 return t; 1038 } 1039 1040 @Override visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index)1041 public void visitLocalVariable(final String name, final String desc, 1042 final String signature, final Label start, final Label end, 1043 final int index) { 1044 buf.setLength(0); 1045 buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' '); 1046 appendDescriptor(FIELD_DESCRIPTOR, desc); 1047 buf.append(' '); 1048 appendLabel(start); 1049 buf.append(' '); 1050 appendLabel(end); 1051 buf.append(' ').append(index).append('\n'); 1052 1053 if (signature != null) { 1054 buf.append(tab2); 1055 appendDescriptor(FIELD_SIGNATURE, signature); 1056 1057 TraceSignatureVisitor sv = new TraceSignatureVisitor(0); 1058 SignatureReader r = new SignatureReader(signature); 1059 r.acceptType(sv); 1060 buf.append(tab2).append("// declaration: ") 1061 .append(sv.getDeclaration()).append('\n'); 1062 } 1063 text.add(buf.toString()); 1064 } 1065 1066 @Override visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible)1067 public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, 1068 Label[] start, Label[] end, int[] index, String desc, 1069 boolean visible) { 1070 buf.setLength(0); 1071 buf.append(tab2).append("LOCALVARIABLE @"); 1072 appendDescriptor(FIELD_DESCRIPTOR, desc); 1073 buf.append('('); 1074 text.add(buf.toString()); 1075 Textifier t = createTextifier(); 1076 text.add(t.getText()); 1077 buf.setLength(0); 1078 buf.append(") : "); 1079 appendTypeReference(typeRef); 1080 buf.append(", ").append(typePath); 1081 for (int i = 0; i < start.length; ++i) { 1082 buf.append(" [ "); 1083 appendLabel(start[i]); 1084 buf.append(" - "); 1085 appendLabel(end[i]); 1086 buf.append(" - ").append(index[i]).append(" ]"); 1087 } 1088 buf.append(visible ? "\n" : " // invisible\n"); 1089 text.add(buf.toString()); 1090 return t; 1091 } 1092 1093 @Override visitLineNumber(final int line, final Label start)1094 public void visitLineNumber(final int line, final Label start) { 1095 buf.setLength(0); 1096 buf.append(tab2).append("LINENUMBER ").append(line).append(' '); 1097 appendLabel(start); 1098 buf.append('\n'); 1099 text.add(buf.toString()); 1100 } 1101 1102 @Override visitMaxs(final int maxStack, final int maxLocals)1103 public void visitMaxs(final int maxStack, final int maxLocals) { 1104 buf.setLength(0); 1105 buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n'); 1106 text.add(buf.toString()); 1107 1108 buf.setLength(0); 1109 buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n'); 1110 text.add(buf.toString()); 1111 } 1112 1113 @Override visitMethodEnd()1114 public void visitMethodEnd() { 1115 } 1116 1117 // ------------------------------------------------------------------------ 1118 // Common methods 1119 // ------------------------------------------------------------------------ 1120 1121 /** 1122 * Prints a disassembled view of the given annotation. 1123 * 1124 * @param desc 1125 * the class descriptor of the annotation class. 1126 * @param visible 1127 * <tt>true</tt> if the annotation is visible at runtime. 1128 * @return a visitor to visit the annotation values. 1129 */ visitAnnotation(final String desc, final boolean visible)1130 public Textifier visitAnnotation(final String desc, final boolean visible) { 1131 buf.setLength(0); 1132 buf.append(tab).append('@'); 1133 appendDescriptor(FIELD_DESCRIPTOR, desc); 1134 buf.append('('); 1135 text.add(buf.toString()); 1136 Textifier t = createTextifier(); 1137 text.add(t.getText()); 1138 text.add(visible ? ")\n" : ") // invisible\n"); 1139 return t; 1140 } 1141 1142 /** 1143 * Prints a disassembled view of the given type annotation. 1144 * 1145 * @param typeRef 1146 * a reference to the annotated type. See {@link TypeReference}. 1147 * @param typePath 1148 * the path to the annotated type argument, wildcard bound, array 1149 * element type, or static inner type within 'typeRef'. May be 1150 * <tt>null</tt> if the annotation targets 'typeRef' as a whole. 1151 * @param desc 1152 * the class descriptor of the annotation class. 1153 * @param visible 1154 * <tt>true</tt> if the annotation is visible at runtime. 1155 * @return a visitor to visit the annotation values. 1156 */ visitTypeAnnotation(final int typeRef, final TypePath typePath, final String desc, final boolean visible)1157 public Textifier visitTypeAnnotation(final int typeRef, 1158 final TypePath typePath, final String desc, final boolean visible) { 1159 buf.setLength(0); 1160 buf.append(tab).append('@'); 1161 appendDescriptor(FIELD_DESCRIPTOR, desc); 1162 buf.append('('); 1163 text.add(buf.toString()); 1164 Textifier t = createTextifier(); 1165 text.add(t.getText()); 1166 buf.setLength(0); 1167 buf.append(") : "); 1168 appendTypeReference(typeRef); 1169 buf.append(", ").append(typePath); 1170 buf.append(visible ? "\n" : " // invisible\n"); 1171 text.add(buf.toString()); 1172 return t; 1173 } 1174 1175 /** 1176 * Prints a disassembled view of the given attribute. 1177 * 1178 * @param attr 1179 * an attribute. 1180 */ visitAttribute(final Attribute attr)1181 public void visitAttribute(final Attribute attr) { 1182 buf.setLength(0); 1183 buf.append(tab).append("ATTRIBUTE "); 1184 appendDescriptor(-1, attr.type); 1185 1186 if (attr instanceof Textifiable) { 1187 ((Textifiable) attr).textify(buf, null); 1188 } else { 1189 buf.append(" : unknown\n"); 1190 } 1191 1192 text.add(buf.toString()); 1193 } 1194 1195 // ------------------------------------------------------------------------ 1196 // Utility methods 1197 // ------------------------------------------------------------------------ 1198 1199 /** 1200 * Creates a new TraceVisitor instance. 1201 * 1202 * @return a new TraceVisitor. 1203 */ createTextifier()1204 protected Textifier createTextifier() { 1205 return new Textifier(); 1206 } 1207 1208 /** 1209 * Appends an internal name, a type descriptor or a type signature to 1210 * {@link #buf buf}. 1211 * 1212 * @param type 1213 * indicates if desc is an internal name, a field descriptor, a 1214 * method descriptor, a class signature, ... 1215 * @param desc 1216 * an internal name, type descriptor, or type signature. May be 1217 * <tt>null</tt>. 1218 */ appendDescriptor(final int type, final String desc)1219 protected void appendDescriptor(final int type, final String desc) { 1220 if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE 1221 || type == METHOD_SIGNATURE) { 1222 if (desc != null) { 1223 buf.append("// signature ").append(desc).append('\n'); 1224 } 1225 } else { 1226 buf.append(desc); 1227 } 1228 } 1229 1230 /** 1231 * Appends the name of the given label to {@link #buf buf}. Creates a new 1232 * label name if the given label does not yet have one. 1233 * 1234 * @param l 1235 * a label. 1236 */ appendLabel(final Label l)1237 protected void appendLabel(final Label l) { 1238 if (labelNames == null) { 1239 labelNames = new HashMap<Label, String>(); 1240 } 1241 String name = labelNames.get(l); 1242 if (name == null) { 1243 name = "L" + labelNames.size(); 1244 labelNames.put(l, name); 1245 } 1246 buf.append(name); 1247 } 1248 1249 /** 1250 * Appends the information about the given handle to {@link #buf buf}. 1251 * 1252 * @param h 1253 * a handle, non null. 1254 */ appendHandle(final Handle h)1255 protected void appendHandle(final Handle h) { 1256 int tag = h.getTag(); 1257 buf.append("// handle kind 0x").append(Integer.toHexString(tag)) 1258 .append(" : "); 1259 boolean isMethodHandle = false; 1260 switch (tag) { 1261 case Opcodes.H_GETFIELD: 1262 buf.append("GETFIELD"); 1263 break; 1264 case Opcodes.H_GETSTATIC: 1265 buf.append("GETSTATIC"); 1266 break; 1267 case Opcodes.H_PUTFIELD: 1268 buf.append("PUTFIELD"); 1269 break; 1270 case Opcodes.H_PUTSTATIC: 1271 buf.append("PUTSTATIC"); 1272 break; 1273 case Opcodes.H_INVOKEINTERFACE: 1274 buf.append("INVOKEINTERFACE"); 1275 isMethodHandle = true; 1276 break; 1277 case Opcodes.H_INVOKESPECIAL: 1278 buf.append("INVOKESPECIAL"); 1279 isMethodHandle = true; 1280 break; 1281 case Opcodes.H_INVOKESTATIC: 1282 buf.append("INVOKESTATIC"); 1283 isMethodHandle = true; 1284 break; 1285 case Opcodes.H_INVOKEVIRTUAL: 1286 buf.append("INVOKEVIRTUAL"); 1287 isMethodHandle = true; 1288 break; 1289 case Opcodes.H_NEWINVOKESPECIAL: 1290 buf.append("NEWINVOKESPECIAL"); 1291 isMethodHandle = true; 1292 break; 1293 } 1294 buf.append('\n'); 1295 buf.append(tab3); 1296 appendDescriptor(INTERNAL_NAME, h.getOwner()); 1297 buf.append('.'); 1298 buf.append(h.getName()); 1299 if(!isMethodHandle){ 1300 buf.append('('); 1301 } 1302 appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc()); 1303 if(!isMethodHandle){ 1304 buf.append(')'); 1305 } 1306 } 1307 1308 /** 1309 * Appends a string representation of the given access modifiers to 1310 * {@link #buf buf}. 1311 * 1312 * @param access 1313 * some access modifiers. 1314 */ appendAccess(final int access)1315 private void appendAccess(final int access) { 1316 if ((access & Opcodes.ACC_PUBLIC) != 0) { 1317 buf.append("public "); 1318 } 1319 if ((access & Opcodes.ACC_PRIVATE) != 0) { 1320 buf.append("private "); 1321 } 1322 if ((access & Opcodes.ACC_PROTECTED) != 0) { 1323 buf.append("protected "); 1324 } 1325 if ((access & Opcodes.ACC_FINAL) != 0) { 1326 buf.append("final "); 1327 } 1328 if ((access & Opcodes.ACC_STATIC) != 0) { 1329 buf.append("static "); 1330 } 1331 if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { 1332 buf.append("synchronized "); 1333 } 1334 if ((access & Opcodes.ACC_VOLATILE) != 0) { 1335 buf.append("volatile "); 1336 } 1337 if ((access & Opcodes.ACC_TRANSIENT) != 0) { 1338 buf.append("transient "); 1339 } 1340 if ((access & Opcodes.ACC_ABSTRACT) != 0) { 1341 buf.append("abstract "); 1342 } 1343 if ((access & Opcodes.ACC_STRICT) != 0) { 1344 buf.append("strictfp "); 1345 } 1346 if ((access & Opcodes.ACC_SYNTHETIC) != 0) { 1347 buf.append("synthetic "); 1348 } 1349 if ((access & Opcodes.ACC_MANDATED) != 0) { 1350 buf.append("mandated "); 1351 } 1352 if ((access & Opcodes.ACC_ENUM) != 0) { 1353 buf.append("enum "); 1354 } 1355 } 1356 appendComa(final int i)1357 private void appendComa(final int i) { 1358 if (i != 0) { 1359 buf.append(", "); 1360 } 1361 } 1362 appendTypeReference(final int typeRef)1363 private void appendTypeReference(final int typeRef) { 1364 TypeReference ref = new TypeReference(typeRef); 1365 switch (ref.getSort()) { 1366 case TypeReference.CLASS_TYPE_PARAMETER: 1367 buf.append("CLASS_TYPE_PARAMETER ").append( 1368 ref.getTypeParameterIndex()); 1369 break; 1370 case TypeReference.METHOD_TYPE_PARAMETER: 1371 buf.append("METHOD_TYPE_PARAMETER ").append( 1372 ref.getTypeParameterIndex()); 1373 break; 1374 case TypeReference.CLASS_EXTENDS: 1375 buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex()); 1376 break; 1377 case TypeReference.CLASS_TYPE_PARAMETER_BOUND: 1378 buf.append("CLASS_TYPE_PARAMETER_BOUND ") 1379 .append(ref.getTypeParameterIndex()).append(", ") 1380 .append(ref.getTypeParameterBoundIndex()); 1381 break; 1382 case TypeReference.METHOD_TYPE_PARAMETER_BOUND: 1383 buf.append("METHOD_TYPE_PARAMETER_BOUND ") 1384 .append(ref.getTypeParameterIndex()).append(", ") 1385 .append(ref.getTypeParameterBoundIndex()); 1386 break; 1387 case TypeReference.FIELD: 1388 buf.append("FIELD"); 1389 break; 1390 case TypeReference.METHOD_RETURN: 1391 buf.append("METHOD_RETURN"); 1392 break; 1393 case TypeReference.METHOD_RECEIVER: 1394 buf.append("METHOD_RECEIVER"); 1395 break; 1396 case TypeReference.METHOD_FORMAL_PARAMETER: 1397 buf.append("METHOD_FORMAL_PARAMETER ").append( 1398 ref.getFormalParameterIndex()); 1399 break; 1400 case TypeReference.THROWS: 1401 buf.append("THROWS ").append(ref.getExceptionIndex()); 1402 break; 1403 case TypeReference.LOCAL_VARIABLE: 1404 buf.append("LOCAL_VARIABLE"); 1405 break; 1406 case TypeReference.RESOURCE_VARIABLE: 1407 buf.append("RESOURCE_VARIABLE"); 1408 break; 1409 case TypeReference.EXCEPTION_PARAMETER: 1410 buf.append("EXCEPTION_PARAMETER ").append( 1411 ref.getTryCatchBlockIndex()); 1412 break; 1413 case TypeReference.INSTANCEOF: 1414 buf.append("INSTANCEOF"); 1415 break; 1416 case TypeReference.NEW: 1417 buf.append("NEW"); 1418 break; 1419 case TypeReference.CONSTRUCTOR_REFERENCE: 1420 buf.append("CONSTRUCTOR_REFERENCE"); 1421 break; 1422 case TypeReference.METHOD_REFERENCE: 1423 buf.append("METHOD_REFERENCE"); 1424 break; 1425 case TypeReference.CAST: 1426 buf.append("CAST ").append(ref.getTypeArgumentIndex()); 1427 break; 1428 case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: 1429 buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append( 1430 ref.getTypeArgumentIndex()); 1431 break; 1432 case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT: 1433 buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append( 1434 ref.getTypeArgumentIndex()); 1435 break; 1436 case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: 1437 buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append( 1438 ref.getTypeArgumentIndex()); 1439 break; 1440 case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT: 1441 buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append( 1442 ref.getTypeArgumentIndex()); 1443 break; 1444 } 1445 } 1446 appendFrameTypes(final int n, final Object[] o)1447 private void appendFrameTypes(final int n, final Object[] o) { 1448 for (int i = 0; i < n; ++i) { 1449 if (i > 0) { 1450 buf.append(' '); 1451 } 1452 if (o[i] instanceof String) { 1453 String desc = (String) o[i]; 1454 if (desc.startsWith("[")) { 1455 appendDescriptor(FIELD_DESCRIPTOR, desc); 1456 } else { 1457 appendDescriptor(INTERNAL_NAME, desc); 1458 } 1459 } else if (o[i] instanceof Integer) { 1460 switch (((Integer) o[i]).intValue()) { 1461 case 0: 1462 appendDescriptor(FIELD_DESCRIPTOR, "T"); 1463 break; 1464 case 1: 1465 appendDescriptor(FIELD_DESCRIPTOR, "I"); 1466 break; 1467 case 2: 1468 appendDescriptor(FIELD_DESCRIPTOR, "F"); 1469 break; 1470 case 3: 1471 appendDescriptor(FIELD_DESCRIPTOR, "D"); 1472 break; 1473 case 4: 1474 appendDescriptor(FIELD_DESCRIPTOR, "J"); 1475 break; 1476 case 5: 1477 appendDescriptor(FIELD_DESCRIPTOR, "N"); 1478 break; 1479 case 6: 1480 appendDescriptor(FIELD_DESCRIPTOR, "U"); 1481 break; 1482 } 1483 } else { 1484 appendLabel((Label) o[i]); 1485 } 1486 } 1487 } 1488 } 1489