1 /* 2 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.classfile; 27 28 import java.io.DataOutputStream; 29 import java.io.IOException; 30 import java.io.OutputStream; 31 import java.util.Iterator; 32 33 /** 34 * See JVMS, section 4.5. 35 * 36 * <p><b>This is NOT part of any supported API. 37 * If you write code that depends on this, you do so at your own risk. 38 * This code and its internal interfaces are subject to change or 39 * deletion without notice.</b> 40 */ 41 public class ConstantPool { 42 43 public static class InvalidIndex extends ConstantPoolException { 44 private static final long serialVersionUID = -4350294289300939730L; 45 InvalidIndex(int index) { 46 super(index); 47 } 48 49 @Override 50 public String getMessage() { 51 // i18n 52 return "invalid index #" + index; 53 } 54 } 55 56 public static class UnexpectedEntry extends ConstantPoolException { 57 private static final long serialVersionUID = 6986335935377933211L; 58 UnexpectedEntry(int index, int expected_tag, int found_tag) { 59 super(index); 60 this.expected_tag = expected_tag; 61 this.found_tag = found_tag; 62 } 63 64 @Override 65 public String getMessage() { 66 // i18n? 67 return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag; 68 } 69 70 public final int expected_tag; 71 public final int found_tag; 72 } 73 74 public static class InvalidEntry extends ConstantPoolException { 75 private static final long serialVersionUID = 1000087545585204447L; 76 InvalidEntry(int index, int tag) { 77 super(index); 78 this.tag = tag; 79 } 80 81 @Override 82 public String getMessage() { 83 // i18n? 84 return "unexpected tag at #" + index + ": " + tag; 85 } 86 87 public final int tag; 88 } 89 90 public static class EntryNotFound extends ConstantPoolException { 91 private static final long serialVersionUID = 2885537606468581850L; 92 EntryNotFound(Object value) { 93 super(-1); 94 this.value = value; 95 } 96 97 @Override 98 public String getMessage() { 99 // i18n? 100 return "value not found: " + value; 101 } 102 103 public final Object value; 104 } 105 106 public static final int CONSTANT_Utf8 = 1; 107 public static final int CONSTANT_Integer = 3; 108 public static final int CONSTANT_Float = 4; 109 public static final int CONSTANT_Long = 5; 110 public static final int CONSTANT_Double = 6; 111 public static final int CONSTANT_Class = 7; 112 public static final int CONSTANT_String = 8; 113 public static final int CONSTANT_Fieldref = 9; 114 public static final int CONSTANT_Methodref = 10; 115 public static final int CONSTANT_InterfaceMethodref = 11; 116 public static final int CONSTANT_NameAndType = 12; 117 public static final int CONSTANT_MethodHandle = 15; 118 public static final int CONSTANT_MethodType = 16; 119 public static final int CONSTANT_InvokeDynamic = 18; 120 121 public static enum RefKind { 122 REF_getField(1, "getfield"), 123 REF_getStatic(2, "getstatic"), 124 REF_putField(3, "putfield"), 125 REF_putStatic(4, "putstatic"), 126 REF_invokeVirtual(5, "invokevirtual"), 127 REF_invokeStatic(6, "invokestatic"), 128 REF_invokeSpecial(7, "invokespecial"), 129 REF_newInvokeSpecial(8, "newinvokespecial"), 130 REF_invokeInterface(9, "invokeinterface"); 131 132 public final int tag; 133 public final String name; 134 135 RefKind(int tag, String name) { 136 this.tag = tag; 137 this.name = name; 138 } 139 140 static RefKind getRefkind(int tag) { 141 switch(tag) { 142 case 1: 143 return REF_getField; 144 case 2: 145 return REF_getStatic; 146 case 3: 147 return REF_putField; 148 case 4: 149 return REF_putStatic; 150 case 5: 151 return REF_invokeVirtual; 152 case 6: 153 return REF_invokeStatic; 154 case 7: 155 return REF_invokeSpecial; 156 case 8: 157 return REF_newInvokeSpecial; 158 case 9: 159 return REF_invokeInterface; 160 default: 161 return null; 162 } 163 } 164 } 165 166 ConstantPool(ClassReader cr) throws IOException, InvalidEntry { 167 int count = cr.readUnsignedShort(); 168 pool = new CPInfo[count]; 169 for (int i = 1; i < count; i++) { 170 int tag = cr.readUnsignedByte(); 171 switch (tag) { 172 case CONSTANT_Class: 173 pool[i] = new CONSTANT_Class_info(this, cr); 174 break; 175 176 case CONSTANT_Double: 177 pool[i] = new CONSTANT_Double_info(cr); 178 i++; 179 break; 180 181 case CONSTANT_Fieldref: 182 pool[i] = new CONSTANT_Fieldref_info(this, cr); 183 break; 184 185 case CONSTANT_Float: 186 pool[i] = new CONSTANT_Float_info(cr); 187 break; 188 189 case CONSTANT_Integer: 190 pool[i] = new CONSTANT_Integer_info(cr); 191 break; 192 193 case CONSTANT_InterfaceMethodref: 194 pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr); 195 break; 196 197 case CONSTANT_InvokeDynamic: 198 pool[i] = new CONSTANT_InvokeDynamic_info(this, cr); 199 break; 200 201 case CONSTANT_Long: 202 pool[i] = new CONSTANT_Long_info(cr); 203 i++; 204 break; 205 206 case CONSTANT_MethodHandle: 207 pool[i] = new CONSTANT_MethodHandle_info(this, cr); 208 break; 209 210 case CONSTANT_MethodType: 211 pool[i] = new CONSTANT_MethodType_info(this, cr); 212 break; 213 214 case CONSTANT_Methodref: 215 pool[i] = new CONSTANT_Methodref_info(this, cr); 216 break; 217 218 case CONSTANT_NameAndType: 219 pool[i] = new CONSTANT_NameAndType_info(this, cr); 220 break; 221 222 case CONSTANT_String: 223 pool[i] = new CONSTANT_String_info(this, cr); 224 break; 225 226 case CONSTANT_Utf8: 227 pool[i] = new CONSTANT_Utf8_info(cr); 228 break; 229 230 default: 231 throw new InvalidEntry(i, tag); 232 } 233 } 234 } 235 236 public ConstantPool(CPInfo[] pool) { 237 this.pool = pool; 238 } 239 240 public int size() { 241 return pool.length; 242 } 243 244 public int byteLength() { 245 int length = 2; 246 for (int i = 1; i < size(); ) { 247 CPInfo cpInfo = pool[i]; 248 length += cpInfo.byteLength(); 249 i += cpInfo.size(); 250 } 251 return length; 252 } 253 254 public CPInfo get(int index) throws InvalidIndex { 255 if (index <= 0 || index >= pool.length) 256 throw new InvalidIndex(index); 257 CPInfo info = pool[index]; 258 if (info == null) { 259 // this occurs for indices referencing the "second half" of an 260 // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long 261 throw new InvalidIndex(index); 262 } 263 return pool[index]; 264 } 265 266 private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry { 267 CPInfo info = get(index); 268 if (info.getTag() != expected_type) 269 throw new UnexpectedEntry(index, expected_type, info.getTag()); 270 return info; 271 } 272 273 public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry { 274 return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8)); 275 } 276 277 public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry { 278 return ((CONSTANT_Class_info) get(index, CONSTANT_Class)); 279 } 280 281 public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry { 282 return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType)); 283 } 284 285 public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry { 286 return getUTF8Info(index).value; 287 } 288 289 public int getUTF8Index(String value) throws EntryNotFound { 290 for (int i = 1; i < pool.length; i++) { 291 CPInfo info = pool[i]; 292 if (info instanceof CONSTANT_Utf8_info && 293 ((CONSTANT_Utf8_info) info).value.equals(value)) 294 return i; 295 } 296 throw new EntryNotFound(value); 297 } 298 299 public Iterable<CPInfo> entries() { 300 return new Iterable<CPInfo>() { 301 public Iterator<CPInfo> iterator() { 302 return new Iterator<CPInfo>() { 303 304 public boolean hasNext() { 305 return next < pool.length; 306 } 307 308 public CPInfo next() { 309 current = pool[next]; 310 switch (current.getTag()) { 311 case CONSTANT_Double: 312 case CONSTANT_Long: 313 next += 2; 314 break; 315 default: 316 next += 1; 317 } 318 return current; 319 } 320 321 public void remove() { 322 throw new UnsupportedOperationException(); 323 } 324 325 private CPInfo current; 326 private int next = 1; 327 328 }; 329 } 330 }; 331 } 332 333 private CPInfo[] pool; 334 335 public interface Visitor<R,P> { 336 R visitClass(CONSTANT_Class_info info, P p); 337 R visitDouble(CONSTANT_Double_info info, P p); 338 R visitFieldref(CONSTANT_Fieldref_info info, P p); 339 R visitFloat(CONSTANT_Float_info info, P p); 340 R visitInteger(CONSTANT_Integer_info info, P p); 341 R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p); 342 R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p); 343 R visitLong(CONSTANT_Long_info info, P p); 344 R visitNameAndType(CONSTANT_NameAndType_info info, P p); 345 R visitMethodref(CONSTANT_Methodref_info info, P p); 346 R visitMethodHandle(CONSTANT_MethodHandle_info info, P p); 347 R visitMethodType(CONSTANT_MethodType_info info, P p); 348 R visitString(CONSTANT_String_info info, P p); 349 R visitUtf8(CONSTANT_Utf8_info info, P p); 350 } 351 352 public static abstract class CPInfo { 353 CPInfo() { 354 this.cp = null; 355 } 356 357 CPInfo(ConstantPool cp) { 358 this.cp = cp; 359 } 360 361 public abstract int getTag(); 362 363 /** The number of slots in the constant pool used by this entry. 364 * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */ 365 public int size() { 366 return 1; 367 } 368 369 public abstract int byteLength(); 370 371 public abstract <R,D> R accept(Visitor<R,D> visitor, D data); 372 373 protected final ConstantPool cp; 374 } 375 376 public static abstract class CPRefInfo extends CPInfo { 377 protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException { 378 super(cp); 379 this.tag = tag; 380 class_index = cr.readUnsignedShort(); 381 name_and_type_index = cr.readUnsignedShort(); 382 } 383 384 protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) { 385 super(cp); 386 this.tag = tag; 387 this.class_index = class_index; 388 this.name_and_type_index = name_and_type_index; 389 } 390 391 public int getTag() { 392 return tag; 393 } 394 395 public int byteLength() { 396 return 5; 397 } 398 399 public CONSTANT_Class_info getClassInfo() throws ConstantPoolException { 400 return cp.getClassInfo(class_index); 401 } 402 403 public String getClassName() throws ConstantPoolException { 404 return cp.getClassInfo(class_index).getName(); 405 } 406 407 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { 408 return cp.getNameAndTypeInfo(name_and_type_index); 409 } 410 411 public final int tag; 412 public final int class_index; 413 public final int name_and_type_index; 414 } 415 416 public static class CONSTANT_Class_info extends CPInfo { 417 CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException { 418 super(cp); 419 name_index = cr.readUnsignedShort(); 420 } 421 422 public CONSTANT_Class_info(ConstantPool cp, int name_index) { 423 super(cp); 424 this.name_index = name_index; 425 } 426 427 public int getTag() { 428 return CONSTANT_Class; 429 } 430 431 public int byteLength() { 432 return 3; 433 } 434 435 /** 436 * Get the raw value of the class referenced by this constant pool entry. 437 * This will either be the name of the class, in internal form, or a 438 * descriptor for an array class. 439 * @return the raw value of the class 440 */ 441 public String getName() throws ConstantPoolException { 442 return cp.getUTF8Value(name_index); 443 } 444 445 /** 446 * If this constant pool entry identifies either a class or interface type, 447 * or a possibly multi-dimensional array of a class of interface type, 448 * return the name of the class or interface in internal form. Otherwise, 449 * (i.e. if this is a possibly multi-dimensional array of a primitive type), 450 * return null. 451 * @return the base class or interface name 452 */ 453 public String getBaseName() throws ConstantPoolException { 454 String name = getName(); 455 if (name.startsWith("[")) { 456 int index = name.indexOf("[L"); 457 if (index == -1) 458 return null; 459 return name.substring(index + 2, name.length() - 1); 460 } else 461 return name; 462 } 463 464 public int getDimensionCount() throws ConstantPoolException { 465 String name = getName(); 466 int count = 0; 467 while (name.charAt(count) == '[') 468 count++; 469 return count; 470 } 471 472 @Override 473 public String toString() { 474 return "CONSTANT_Class_info[name_index: " + name_index + "]"; 475 } 476 477 public <R, D> R accept(Visitor<R, D> visitor, D data) { 478 return visitor.visitClass(this, data); 479 } 480 481 public final int name_index; 482 } 483 484 public static class CONSTANT_Double_info extends CPInfo { 485 CONSTANT_Double_info(ClassReader cr) throws IOException { 486 value = cr.readDouble(); 487 } 488 489 public CONSTANT_Double_info(double value) { 490 this.value = value; 491 } 492 493 public int getTag() { 494 return CONSTANT_Double; 495 } 496 497 public int byteLength() { 498 return 9; 499 } 500 501 @Override 502 public int size() { 503 return 2; 504 } 505 506 @Override 507 public String toString() { 508 return "CONSTANT_Double_info[value: " + value + "]"; 509 } 510 511 public <R, D> R accept(Visitor<R, D> visitor, D data) { 512 return visitor.visitDouble(this, data); 513 } 514 515 public final double value; 516 } 517 518 public static class CONSTANT_Fieldref_info extends CPRefInfo { 519 CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException { 520 super(cp, cr, CONSTANT_Fieldref); 521 } 522 523 public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) { 524 super(cp, CONSTANT_Fieldref, class_index, name_and_type_index); 525 } 526 527 @Override 528 public String toString() { 529 return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 530 } 531 532 public <R, D> R accept(Visitor<R, D> visitor, D data) { 533 return visitor.visitFieldref(this, data); 534 } 535 } 536 537 public static class CONSTANT_Float_info extends CPInfo { 538 CONSTANT_Float_info(ClassReader cr) throws IOException { 539 value = cr.readFloat(); 540 } 541 542 public CONSTANT_Float_info(float value) { 543 this.value = value; 544 } 545 546 public int getTag() { 547 return CONSTANT_Float; 548 } 549 550 public int byteLength() { 551 return 5; 552 } 553 554 @Override 555 public String toString() { 556 return "CONSTANT_Float_info[value: " + value + "]"; 557 } 558 559 public <R, D> R accept(Visitor<R, D> visitor, D data) { 560 return visitor.visitFloat(this, data); 561 } 562 563 public final float value; 564 } 565 566 public static class CONSTANT_Integer_info extends CPInfo { 567 CONSTANT_Integer_info(ClassReader cr) throws IOException { 568 value = cr.readInt(); 569 } 570 571 public CONSTANT_Integer_info(int value) { 572 this.value = value; 573 } 574 575 public int getTag() { 576 return CONSTANT_Integer; 577 } 578 579 public int byteLength() { 580 return 5; 581 } 582 583 @Override 584 public String toString() { 585 return "CONSTANT_Integer_info[value: " + value + "]"; 586 } 587 588 public <R, D> R accept(Visitor<R, D> visitor, D data) { 589 return visitor.visitInteger(this, data); 590 } 591 592 public final int value; 593 } 594 595 public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo { 596 CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException { 597 super(cp, cr, CONSTANT_InterfaceMethodref); 598 } 599 600 public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) { 601 super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index); 602 } 603 604 @Override 605 public String toString() { 606 return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 607 } 608 609 public <R, D> R accept(Visitor<R, D> visitor, D data) { 610 return visitor.visitInterfaceMethodref(this, data); 611 } 612 } 613 614 public static class CONSTANT_InvokeDynamic_info extends CPInfo { 615 CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException { 616 super(cp); 617 bootstrap_method_attr_index = cr.readUnsignedShort(); 618 name_and_type_index = cr.readUnsignedShort(); 619 } 620 621 public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) { 622 super(cp); 623 this.bootstrap_method_attr_index = bootstrap_method_index; 624 this.name_and_type_index = name_and_type_index; 625 } 626 627 public int getTag() { 628 return CONSTANT_InvokeDynamic; 629 } 630 631 public int byteLength() { 632 return 5; 633 } 634 635 @Override 636 public String toString() { 637 return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]"; 638 } 639 640 public <R, D> R accept(Visitor<R, D> visitor, D data) { 641 return visitor.visitInvokeDynamic(this, data); 642 } 643 644 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { 645 return cp.getNameAndTypeInfo(name_and_type_index); 646 } 647 648 public final int bootstrap_method_attr_index; 649 public final int name_and_type_index; 650 } 651 652 public static class CONSTANT_Long_info extends CPInfo { 653 CONSTANT_Long_info(ClassReader cr) throws IOException { 654 value = cr.readLong(); 655 } 656 657 public CONSTANT_Long_info(long value) { 658 this.value = value; 659 } 660 661 public int getTag() { 662 return CONSTANT_Long; 663 } 664 665 @Override 666 public int size() { 667 return 2; 668 } 669 670 public int byteLength() { 671 return 9; 672 } 673 674 @Override 675 public String toString() { 676 return "CONSTANT_Long_info[value: " + value + "]"; 677 } 678 679 public <R, D> R accept(Visitor<R, D> visitor, D data) { 680 return visitor.visitLong(this, data); 681 } 682 683 public final long value; 684 } 685 686 public static class CONSTANT_MethodHandle_info extends CPInfo { 687 CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException { 688 super(cp); 689 reference_kind = RefKind.getRefkind(cr.readUnsignedByte()); 690 reference_index = cr.readUnsignedShort(); 691 } 692 693 public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) { 694 super(cp); 695 this.reference_kind = ref_kind; 696 this.reference_index = member_index; 697 } 698 699 public int getTag() { 700 return CONSTANT_MethodHandle; 701 } 702 703 public int byteLength() { 704 return 4; 705 } 706 707 @Override 708 public String toString() { 709 return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]"; 710 } 711 712 public <R, D> R accept(Visitor<R, D> visitor, D data) { 713 return visitor.visitMethodHandle(this, data); 714 } 715 716 public CPRefInfo getCPRefInfo() throws ConstantPoolException { 717 int expected = CONSTANT_Methodref; 718 int actual = cp.get(reference_index).getTag(); 719 // allow these tag types also: 720 switch (actual) { 721 case CONSTANT_Fieldref: 722 case CONSTANT_InterfaceMethodref: 723 expected = actual; 724 } 725 return (CPRefInfo) cp.get(reference_index, expected); 726 } 727 728 public final RefKind reference_kind; 729 public final int reference_index; 730 } 731 732 public static class CONSTANT_MethodType_info extends CPInfo { 733 CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException { 734 super(cp); 735 descriptor_index = cr.readUnsignedShort(); 736 } 737 738 public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) { 739 super(cp); 740 this.descriptor_index = signature_index; 741 } 742 743 public int getTag() { 744 return CONSTANT_MethodType; 745 } 746 747 public int byteLength() { 748 return 3; 749 } 750 751 @Override 752 public String toString() { 753 return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]"; 754 } 755 756 public <R, D> R accept(Visitor<R, D> visitor, D data) { 757 return visitor.visitMethodType(this, data); 758 } 759 760 public String getType() throws ConstantPoolException { 761 return cp.getUTF8Value(descriptor_index); 762 } 763 764 public final int descriptor_index; 765 } 766 767 public static class CONSTANT_Methodref_info extends CPRefInfo { 768 CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException { 769 super(cp, cr, CONSTANT_Methodref); 770 } 771 772 public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) { 773 super(cp, CONSTANT_Methodref, class_index, name_and_type_index); 774 } 775 776 @Override 777 public String toString() { 778 return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 779 } 780 781 public <R, D> R accept(Visitor<R, D> visitor, D data) { 782 return visitor.visitMethodref(this, data); 783 } 784 } 785 786 public static class CONSTANT_NameAndType_info extends CPInfo { 787 CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException { 788 super(cp); 789 name_index = cr.readUnsignedShort(); 790 type_index = cr.readUnsignedShort(); 791 } 792 793 public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) { 794 super(cp); 795 this.name_index = name_index; 796 this.type_index = type_index; 797 } 798 799 public int getTag() { 800 return CONSTANT_NameAndType; 801 } 802 803 public int byteLength() { 804 return 5; 805 } 806 807 public String getName() throws ConstantPoolException { 808 return cp.getUTF8Value(name_index); 809 } 810 811 public String getType() throws ConstantPoolException { 812 return cp.getUTF8Value(type_index); 813 } 814 815 public <R, D> R accept(Visitor<R, D> visitor, D data) { 816 return visitor.visitNameAndType(this, data); 817 } 818 819 @Override 820 public String toString() { 821 return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]"; 822 } 823 824 public final int name_index; 825 public final int type_index; 826 } 827 828 public static class CONSTANT_String_info extends CPInfo { 829 CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException { 830 super(cp); 831 string_index = cr.readUnsignedShort(); 832 } 833 834 public CONSTANT_String_info(ConstantPool cp, int string_index) { 835 super(cp); 836 this.string_index = string_index; 837 } 838 839 public int getTag() { 840 return CONSTANT_String; 841 } 842 843 public int byteLength() { 844 return 3; 845 } 846 847 public String getString() throws ConstantPoolException { 848 return cp.getUTF8Value(string_index); 849 } 850 851 public <R, D> R accept(Visitor<R, D> visitor, D data) { 852 return visitor.visitString(this, data); 853 } 854 855 @Override 856 public String toString() { 857 return "CONSTANT_String_info[class_index: " + string_index + "]"; 858 } 859 860 public final int string_index; 861 } 862 863 public static class CONSTANT_Utf8_info extends CPInfo { 864 CONSTANT_Utf8_info(ClassReader cr) throws IOException { 865 value = cr.readUTF(); 866 } 867 868 public CONSTANT_Utf8_info(String value) { 869 this.value = value; 870 } 871 872 public int getTag() { 873 return CONSTANT_Utf8; 874 } 875 876 public int byteLength() { 877 class SizeOutputStream extends OutputStream { 878 @Override 879 public void write(int b) { 880 size++; 881 } 882 int size; 883 } 884 SizeOutputStream sizeOut = new SizeOutputStream(); 885 DataOutputStream out = new DataOutputStream(sizeOut); 886 try { out.writeUTF(value); } catch (IOException ignore) { } 887 return 1 + sizeOut.size; 888 } 889 890 @Override 891 public String toString() { 892 if (value.length() < 32 && isPrintableAscii(value)) 893 return "CONSTANT_Utf8_info[value: \"" + value + "\"]"; 894 else 895 return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]"; 896 } 897 898 static boolean isPrintableAscii(String s) { 899 for (int i = 0; i < s.length(); i++) { 900 char c = s.charAt(i); 901 if (c < 32 || c >= 127) 902 return false; 903 } 904 return true; 905 } 906 907 public <R, D> R accept(Visitor<R, D> visitor, D data) { 908 return visitor.visitUtf8(this, data); 909 } 910 911 public final String value; 912 } 913 914 }