1/* 2 * Copyright (c) 2007, 2016, 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 26package com.sun.tools.classfile; 27 28import java.io.DataOutputStream; 29import java.io.IOException; 30import java.io.OutputStream; 31import 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 */ 41public 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 public static final int CONSTANT_Module = 19; 121 public static final int CONSTANT_Package = 20; 122 123 public static enum RefKind { 124 REF_getField(1), 125 REF_getStatic(2), 126 REF_putField(3), 127 REF_putStatic(4), 128 REF_invokeVirtual(5), 129 REF_invokeStatic(6), 130 REF_invokeSpecial(7), 131 REF_newInvokeSpecial(8), 132 REF_invokeInterface(9); 133 134 public final int tag; 135 136 RefKind(int tag) { 137 this.tag = tag; 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_Module: 219 pool[i] = new CONSTANT_Module_info(this, cr); 220 break; 221 222 case CONSTANT_NameAndType: 223 pool[i] = new CONSTANT_NameAndType_info(this, cr); 224 break; 225 226 case CONSTANT_Package: 227 pool[i] = new CONSTANT_Package_info(this, cr); 228 break; 229 230 case CONSTANT_String: 231 pool[i] = new CONSTANT_String_info(this, cr); 232 break; 233 234 case CONSTANT_Utf8: 235 pool[i] = new CONSTANT_Utf8_info(cr); 236 break; 237 238 default: 239 throw new InvalidEntry(i, tag); 240 } 241 } 242 } 243 244 public ConstantPool(CPInfo[] pool) { 245 this.pool = pool; 246 } 247 248 public int size() { 249 return pool.length; 250 } 251 252 public int byteLength() { 253 int length = 2; 254 for (int i = 1; i < size(); ) { 255 CPInfo cpInfo = pool[i]; 256 length += cpInfo.byteLength(); 257 i += cpInfo.size(); 258 } 259 return length; 260 } 261 262 public CPInfo get(int index) throws InvalidIndex { 263 if (index <= 0 || index >= pool.length) 264 throw new InvalidIndex(index); 265 CPInfo info = pool[index]; 266 if (info == null) { 267 // this occurs for indices referencing the "second half" of an 268 // 8 byte constant, such as CONSTANT_Double or CONSTANT_Long 269 throw new InvalidIndex(index); 270 } 271 return pool[index]; 272 } 273 274 private CPInfo get(int index, int expected_type) throws InvalidIndex, UnexpectedEntry { 275 CPInfo info = get(index); 276 if (info.getTag() != expected_type) 277 throw new UnexpectedEntry(index, expected_type, info.getTag()); 278 return info; 279 } 280 281 public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry { 282 return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8)); 283 } 284 285 public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry { 286 return ((CONSTANT_Class_info) get(index, CONSTANT_Class)); 287 } 288 289 public CONSTANT_Module_info getModuleInfo(int index) throws InvalidIndex, UnexpectedEntry { 290 return ((CONSTANT_Module_info) get(index, CONSTANT_Module)); 291 } 292 293 public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry { 294 return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType)); 295 } 296 297 public CONSTANT_Package_info getPackageInfo(int index) throws InvalidIndex, UnexpectedEntry { 298 return ((CONSTANT_Package_info) get(index, CONSTANT_Package)); 299 } 300 301 public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry { 302 return getUTF8Info(index).value; 303 } 304 305 public int getUTF8Index(String value) throws EntryNotFound { 306 for (int i = 1; i < pool.length; i++) { 307 CPInfo info = pool[i]; 308 if (info instanceof CONSTANT_Utf8_info && 309 ((CONSTANT_Utf8_info) info).value.equals(value)) 310 return i; 311 } 312 throw new EntryNotFound(value); 313 } 314 315 public Iterable<CPInfo> entries() { 316 return () -> new Iterator<CPInfo>() { 317 318 public boolean hasNext() { 319 return next < pool.length; 320 } 321 322 public CPInfo next() { 323 current = pool[next]; 324 switch (current.getTag()) { 325 case CONSTANT_Double: 326 case CONSTANT_Long: 327 next += 2; 328 break; 329 default: 330 next += 1; 331 } 332 return current; 333 } 334 335 public void remove() { 336 throw new UnsupportedOperationException(); 337 } 338 339 private CPInfo current; 340 private int next = 1; 341 342 }; 343 } 344 345 private CPInfo[] pool; 346 347 public interface Visitor<R,P> { 348 R visitClass(CONSTANT_Class_info info, P p); 349 R visitDouble(CONSTANT_Double_info info, P p); 350 R visitFieldref(CONSTANT_Fieldref_info info, P p); 351 R visitFloat(CONSTANT_Float_info info, P p); 352 R visitInteger(CONSTANT_Integer_info info, P p); 353 R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p); 354 R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p); 355 R visitLong(CONSTANT_Long_info info, P p); 356 R visitMethodref(CONSTANT_Methodref_info info, P p); 357 R visitMethodHandle(CONSTANT_MethodHandle_info info, P p); 358 R visitMethodType(CONSTANT_MethodType_info info, P p); 359 R visitModule(CONSTANT_Module_info info, P p); 360 R visitNameAndType(CONSTANT_NameAndType_info info, P p); 361 R visitPackage(CONSTANT_Package_info info, P p); 362 R visitString(CONSTANT_String_info info, P p); 363 R visitUtf8(CONSTANT_Utf8_info info, P p); 364 } 365 366 public static abstract class CPInfo { 367 CPInfo() { 368 this.cp = null; 369 } 370 371 CPInfo(ConstantPool cp) { 372 this.cp = cp; 373 } 374 375 public abstract int getTag(); 376 377 /** The number of slots in the constant pool used by this entry. 378 * 2 for CONSTANT_Double and CONSTANT_Long; 1 for everything else. */ 379 public int size() { 380 return 1; 381 } 382 383 public abstract int byteLength(); 384 385 public abstract <R,D> R accept(Visitor<R,D> visitor, D data); 386 387 protected final ConstantPool cp; 388 } 389 390 public static abstract class CPRefInfo extends CPInfo { 391 protected CPRefInfo(ConstantPool cp, ClassReader cr, int tag) throws IOException { 392 super(cp); 393 this.tag = tag; 394 class_index = cr.readUnsignedShort(); 395 name_and_type_index = cr.readUnsignedShort(); 396 } 397 398 protected CPRefInfo(ConstantPool cp, int tag, int class_index, int name_and_type_index) { 399 super(cp); 400 this.tag = tag; 401 this.class_index = class_index; 402 this.name_and_type_index = name_and_type_index; 403 } 404 405 public int getTag() { 406 return tag; 407 } 408 409 public int byteLength() { 410 return 5; 411 } 412 413 public CONSTANT_Class_info getClassInfo() throws ConstantPoolException { 414 return cp.getClassInfo(class_index); 415 } 416 417 public String getClassName() throws ConstantPoolException { 418 return cp.getClassInfo(class_index).getName(); 419 } 420 421 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { 422 return cp.getNameAndTypeInfo(name_and_type_index); 423 } 424 425 public final int tag; 426 public final int class_index; 427 public final int name_and_type_index; 428 } 429 430 public static class CONSTANT_Class_info extends CPInfo { 431 CONSTANT_Class_info(ConstantPool cp, ClassReader cr) throws IOException { 432 super(cp); 433 name_index = cr.readUnsignedShort(); 434 } 435 436 public CONSTANT_Class_info(ConstantPool cp, int name_index) { 437 super(cp); 438 this.name_index = name_index; 439 } 440 441 public int getTag() { 442 return CONSTANT_Class; 443 } 444 445 public int byteLength() { 446 return 3; 447 } 448 449 /** 450 * Get the raw value of the class referenced by this constant pool entry. 451 * This will either be the name of the class, in internal form, or a 452 * descriptor for an array class. 453 * @return the raw value of the class 454 */ 455 public String getName() throws ConstantPoolException { 456 return cp.getUTF8Value(name_index); 457 } 458 459 /** 460 * If this constant pool entry identifies either a class or interface type, 461 * or a possibly multi-dimensional array of a class of interface type, 462 * return the name of the class or interface in internal form. Otherwise, 463 * (i.e. if this is a possibly multi-dimensional array of a primitive type), 464 * return null. 465 * @return the base class or interface name 466 */ 467 public String getBaseName() throws ConstantPoolException { 468 String name = getName(); 469 if (name.startsWith("[")) { 470 int index = name.indexOf("[L"); 471 if (index == -1) 472 return null; 473 return name.substring(index + 2, name.length() - 1); 474 } else 475 return name; 476 } 477 478 public int getDimensionCount() throws ConstantPoolException { 479 String name = getName(); 480 int count = 0; 481 while (name.charAt(count) == '[') 482 count++; 483 return count; 484 } 485 486 @Override 487 public String toString() { 488 return "CONSTANT_Class_info[name_index: " + name_index + "]"; 489 } 490 491 public <R, D> R accept(Visitor<R, D> visitor, D data) { 492 return visitor.visitClass(this, data); 493 } 494 495 public final int name_index; 496 } 497 498 public static class CONSTANT_Double_info extends CPInfo { 499 CONSTANT_Double_info(ClassReader cr) throws IOException { 500 value = cr.readDouble(); 501 } 502 503 public CONSTANT_Double_info(double value) { 504 this.value = value; 505 } 506 507 public int getTag() { 508 return CONSTANT_Double; 509 } 510 511 public int byteLength() { 512 return 9; 513 } 514 515 @Override 516 public int size() { 517 return 2; 518 } 519 520 @Override 521 public String toString() { 522 return "CONSTANT_Double_info[value: " + value + "]"; 523 } 524 525 public <R, D> R accept(Visitor<R, D> visitor, D data) { 526 return visitor.visitDouble(this, data); 527 } 528 529 public final double value; 530 } 531 532 public static class CONSTANT_Fieldref_info extends CPRefInfo { 533 CONSTANT_Fieldref_info(ConstantPool cp, ClassReader cr) throws IOException { 534 super(cp, cr, CONSTANT_Fieldref); 535 } 536 537 public CONSTANT_Fieldref_info(ConstantPool cp, int class_index, int name_and_type_index) { 538 super(cp, CONSTANT_Fieldref, class_index, name_and_type_index); 539 } 540 541 @Override 542 public String toString() { 543 return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 544 } 545 546 public <R, D> R accept(Visitor<R, D> visitor, D data) { 547 return visitor.visitFieldref(this, data); 548 } 549 } 550 551 public static class CONSTANT_Float_info extends CPInfo { 552 CONSTANT_Float_info(ClassReader cr) throws IOException { 553 value = cr.readFloat(); 554 } 555 556 public CONSTANT_Float_info(float value) { 557 this.value = value; 558 } 559 560 public int getTag() { 561 return CONSTANT_Float; 562 } 563 564 public int byteLength() { 565 return 5; 566 } 567 568 @Override 569 public String toString() { 570 return "CONSTANT_Float_info[value: " + value + "]"; 571 } 572 573 public <R, D> R accept(Visitor<R, D> visitor, D data) { 574 return visitor.visitFloat(this, data); 575 } 576 577 public final float value; 578 } 579 580 public static class CONSTANT_Integer_info extends CPInfo { 581 CONSTANT_Integer_info(ClassReader cr) throws IOException { 582 value = cr.readInt(); 583 } 584 585 public CONSTANT_Integer_info(int value) { 586 this.value = value; 587 } 588 589 public int getTag() { 590 return CONSTANT_Integer; 591 } 592 593 public int byteLength() { 594 return 5; 595 } 596 597 @Override 598 public String toString() { 599 return "CONSTANT_Integer_info[value: " + value + "]"; 600 } 601 602 public <R, D> R accept(Visitor<R, D> visitor, D data) { 603 return visitor.visitInteger(this, data); 604 } 605 606 public final int value; 607 } 608 609 public static class CONSTANT_InterfaceMethodref_info extends CPRefInfo { 610 CONSTANT_InterfaceMethodref_info(ConstantPool cp, ClassReader cr) throws IOException { 611 super(cp, cr, CONSTANT_InterfaceMethodref); 612 } 613 614 public CONSTANT_InterfaceMethodref_info(ConstantPool cp, int class_index, int name_and_type_index) { 615 super(cp, CONSTANT_InterfaceMethodref, class_index, name_and_type_index); 616 } 617 618 @Override 619 public String toString() { 620 return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 621 } 622 623 public <R, D> R accept(Visitor<R, D> visitor, D data) { 624 return visitor.visitInterfaceMethodref(this, data); 625 } 626 } 627 628 public static class CONSTANT_InvokeDynamic_info extends CPInfo { 629 CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException { 630 super(cp); 631 bootstrap_method_attr_index = cr.readUnsignedShort(); 632 name_and_type_index = cr.readUnsignedShort(); 633 } 634 635 public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) { 636 super(cp); 637 this.bootstrap_method_attr_index = bootstrap_method_index; 638 this.name_and_type_index = name_and_type_index; 639 } 640 641 public int getTag() { 642 return CONSTANT_InvokeDynamic; 643 } 644 645 public int byteLength() { 646 return 5; 647 } 648 649 @Override 650 public String toString() { 651 return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]"; 652 } 653 654 public <R, D> R accept(Visitor<R, D> visitor, D data) { 655 return visitor.visitInvokeDynamic(this, data); 656 } 657 658 public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException { 659 return cp.getNameAndTypeInfo(name_and_type_index); 660 } 661 662 public final int bootstrap_method_attr_index; 663 public final int name_and_type_index; 664 } 665 666 public static class CONSTANT_Long_info extends CPInfo { 667 CONSTANT_Long_info(ClassReader cr) throws IOException { 668 value = cr.readLong(); 669 } 670 671 public CONSTANT_Long_info(long value) { 672 this.value = value; 673 } 674 675 public int getTag() { 676 return CONSTANT_Long; 677 } 678 679 @Override 680 public int size() { 681 return 2; 682 } 683 684 public int byteLength() { 685 return 9; 686 } 687 688 @Override 689 public String toString() { 690 return "CONSTANT_Long_info[value: " + value + "]"; 691 } 692 693 public <R, D> R accept(Visitor<R, D> visitor, D data) { 694 return visitor.visitLong(this, data); 695 } 696 697 public final long value; 698 } 699 700 public static class CONSTANT_MethodHandle_info extends CPInfo { 701 CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException { 702 super(cp); 703 reference_kind = RefKind.getRefkind(cr.readUnsignedByte()); 704 reference_index = cr.readUnsignedShort(); 705 } 706 707 public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) { 708 super(cp); 709 this.reference_kind = ref_kind; 710 this.reference_index = member_index; 711 } 712 713 public int getTag() { 714 return CONSTANT_MethodHandle; 715 } 716 717 public int byteLength() { 718 return 4; 719 } 720 721 @Override 722 public String toString() { 723 return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]"; 724 } 725 726 public <R, D> R accept(Visitor<R, D> visitor, D data) { 727 return visitor.visitMethodHandle(this, data); 728 } 729 730 public CPRefInfo getCPRefInfo() throws ConstantPoolException { 731 int expected = CONSTANT_Methodref; 732 int actual = cp.get(reference_index).getTag(); 733 // allow these tag types also: 734 switch (actual) { 735 case CONSTANT_Fieldref: 736 case CONSTANT_InterfaceMethodref: 737 expected = actual; 738 } 739 return (CPRefInfo) cp.get(reference_index, expected); 740 } 741 742 public final RefKind reference_kind; 743 public final int reference_index; 744 } 745 746 public static class CONSTANT_MethodType_info extends CPInfo { 747 CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException { 748 super(cp); 749 descriptor_index = cr.readUnsignedShort(); 750 } 751 752 public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) { 753 super(cp); 754 this.descriptor_index = signature_index; 755 } 756 757 public int getTag() { 758 return CONSTANT_MethodType; 759 } 760 761 public int byteLength() { 762 return 3; 763 } 764 765 @Override 766 public String toString() { 767 return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]"; 768 } 769 770 public <R, D> R accept(Visitor<R, D> visitor, D data) { 771 return visitor.visitMethodType(this, data); 772 } 773 774 public String getType() throws ConstantPoolException { 775 return cp.getUTF8Value(descriptor_index); 776 } 777 778 public final int descriptor_index; 779 } 780 781 public static class CONSTANT_Methodref_info extends CPRefInfo { 782 CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException { 783 super(cp, cr, CONSTANT_Methodref); 784 } 785 786 public CONSTANT_Methodref_info(ConstantPool cp, int class_index, int name_and_type_index) { 787 super(cp, CONSTANT_Methodref, class_index, name_and_type_index); 788 } 789 790 @Override 791 public String toString() { 792 return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]"; 793 } 794 795 public <R, D> R accept(Visitor<R, D> visitor, D data) { 796 return visitor.visitMethodref(this, data); 797 } 798 } 799 800 public static class CONSTANT_Module_info extends CPInfo { 801 CONSTANT_Module_info(ConstantPool cp, ClassReader cr) throws IOException { 802 super(cp); 803 name_index = cr.readUnsignedShort(); 804 } 805 806 public CONSTANT_Module_info(ConstantPool cp, int name_index) { 807 super(cp); 808 this.name_index = name_index; 809 } 810 811 public int getTag() { 812 return CONSTANT_Module; 813 } 814 815 public int byteLength() { 816 return 3; 817 } 818 819 /** 820 * Get the raw value of the module name referenced by this constant pool entry. 821 * This will be the name of the module. 822 * @return the raw value of the module name 823 */ 824 public String getName() throws ConstantPoolException { 825 return cp.getUTF8Value(name_index); 826 } 827 828 @Override 829 public String toString() { 830 return "CONSTANT_Module_info[name_index: " + name_index + "]"; 831 } 832 833 public <R, D> R accept(Visitor<R, D> visitor, D data) { 834 return visitor.visitModule(this, data); 835 } 836 837 public final int name_index; 838 } 839 840 public static class CONSTANT_NameAndType_info extends CPInfo { 841 CONSTANT_NameAndType_info(ConstantPool cp, ClassReader cr) throws IOException { 842 super(cp); 843 name_index = cr.readUnsignedShort(); 844 type_index = cr.readUnsignedShort(); 845 } 846 847 public CONSTANT_NameAndType_info(ConstantPool cp, int name_index, int type_index) { 848 super(cp); 849 this.name_index = name_index; 850 this.type_index = type_index; 851 } 852 853 public int getTag() { 854 return CONSTANT_NameAndType; 855 } 856 857 public int byteLength() { 858 return 5; 859 } 860 861 public String getName() throws ConstantPoolException { 862 return cp.getUTF8Value(name_index); 863 } 864 865 public String getType() throws ConstantPoolException { 866 return cp.getUTF8Value(type_index); 867 } 868 869 public <R, D> R accept(Visitor<R, D> visitor, D data) { 870 return visitor.visitNameAndType(this, data); 871 } 872 873 @Override 874 public String toString() { 875 return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]"; 876 } 877 878 public final int name_index; 879 public final int type_index; 880 } 881 882 public static class CONSTANT_Package_info extends CPInfo { 883 CONSTANT_Package_info(ConstantPool cp, ClassReader cr) throws IOException { 884 super(cp); 885 name_index = cr.readUnsignedShort(); 886 } 887 888 public CONSTANT_Package_info(ConstantPool cp, int name_index) { 889 super(cp); 890 this.name_index = name_index; 891 } 892 893 public int getTag() { 894 return CONSTANT_Package; 895 } 896 897 public int byteLength() { 898 return 3; 899 } 900 901 /** 902 * Get the raw value of the package name referenced by this constant pool entry. 903 * This will be the name of the package, in internal form. 904 * @return the raw value of the module name 905 */ 906 public String getName() throws ConstantPoolException { 907 return cp.getUTF8Value(name_index); 908 } 909 910 @Override 911 public String toString() { 912 return "CONSTANT_Package_info[name_index: " + name_index + "]"; 913 } 914 915 public <R, D> R accept(Visitor<R, D> visitor, D data) { 916 return visitor.visitPackage(this, data); 917 } 918 919 public final int name_index; 920 } 921 922 public static class CONSTANT_String_info extends CPInfo { 923 CONSTANT_String_info(ConstantPool cp, ClassReader cr) throws IOException { 924 super(cp); 925 string_index = cr.readUnsignedShort(); 926 } 927 928 public CONSTANT_String_info(ConstantPool cp, int string_index) { 929 super(cp); 930 this.string_index = string_index; 931 } 932 933 public int getTag() { 934 return CONSTANT_String; 935 } 936 937 public int byteLength() { 938 return 3; 939 } 940 941 public String getString() throws ConstantPoolException { 942 return cp.getUTF8Value(string_index); 943 } 944 945 public <R, D> R accept(Visitor<R, D> visitor, D data) { 946 return visitor.visitString(this, data); 947 } 948 949 @Override 950 public String toString() { 951 return "CONSTANT_String_info[class_index: " + string_index + "]"; 952 } 953 954 public final int string_index; 955 } 956 957 public static class CONSTANT_Utf8_info extends CPInfo { 958 CONSTANT_Utf8_info(ClassReader cr) throws IOException { 959 value = cr.readUTF(); 960 } 961 962 public CONSTANT_Utf8_info(String value) { 963 this.value = value; 964 } 965 966 public int getTag() { 967 return CONSTANT_Utf8; 968 } 969 970 public int byteLength() { 971 class SizeOutputStream extends OutputStream { 972 @Override 973 public void write(int b) { 974 size++; 975 } 976 int size; 977 } 978 SizeOutputStream sizeOut = new SizeOutputStream(); 979 DataOutputStream out = new DataOutputStream(sizeOut); 980 try { out.writeUTF(value); } catch (IOException ignore) { } 981 return 1 + sizeOut.size; 982 } 983 984 @Override 985 public String toString() { 986 if (value.length() < 32 && isPrintableAscii(value)) 987 return "CONSTANT_Utf8_info[value: \"" + value + "\"]"; 988 else 989 return "CONSTANT_Utf8_info[value: (" + value.length() + " chars)]"; 990 } 991 992 static boolean isPrintableAscii(String s) { 993 for (int i = 0; i < s.length(); i++) { 994 char c = s.charAt(i); 995 if (c < 32 || c >= 127) 996 return false; 997 } 998 return true; 999 } 1000 1001 public <R, D> R accept(Visitor<R, D> visitor, D data) { 1002 return visitor.visitUtf8(this, data); 1003 } 1004 1005 public final String value; 1006 } 1007 1008} 1009