src/share/classes/com/sun/tools/classfile/ConstantPool.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 972
694ff82ca68e
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

     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  */
    26 package com.sun.tools.classfile;
    28 import java.io.DataOutputStream;
    29 import java.io.IOException;
    30 import java.io.OutputStream;
    31 import java.util.Iterator;
    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 {
    43     public static class InvalidIndex extends ConstantPoolException {
    44         private static final long serialVersionUID = -4350294289300939730L;
    45         InvalidIndex(int index) {
    46             super(index);
    47         }
    49         @Override
    50         public String getMessage() {
    51             // i18n
    52             return "invalid index #" + index;
    53         }
    54     }
    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         }
    64         @Override
    65         public String getMessage() {
    66             // i18n?
    67             return "unexpected entry at #" + index + " -- expected tag " + expected_tag + ", found " + found_tag;
    68         }
    70         public final int expected_tag;
    71         public final int found_tag;
    72     }
    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         }
    81         @Override
    82         public String getMessage() {
    83             // i18n?
    84             return "unexpected tag at #" + index + ": " + tag;
    85         }
    87         public final int tag;
    88     }
    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         }
    97         @Override
    98         public String getMessage() {
    99             // i18n?
   100             return "value not found: " + value;
   101         }
   103         public final Object value;
   104     }
   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;
   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");
   132         public final int tag;
   133         public final String name;
   135         RefKind(int tag, String name) {
   136             this.tag = tag;
   137             this.name = name;
   138         }
   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     }
   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;
   176             case CONSTANT_Double:
   177                 pool[i] = new CONSTANT_Double_info(cr);
   178                 i++;
   179                 break;
   181             case CONSTANT_Fieldref:
   182                 pool[i] = new CONSTANT_Fieldref_info(this, cr);
   183                 break;
   185             case CONSTANT_Float:
   186                 pool[i] = new CONSTANT_Float_info(cr);
   187                 break;
   189             case CONSTANT_Integer:
   190                 pool[i] = new CONSTANT_Integer_info(cr);
   191                 break;
   193             case CONSTANT_InterfaceMethodref:
   194                 pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
   195                 break;
   197             case CONSTANT_InvokeDynamic:
   198                 pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
   199                 break;
   201             case CONSTANT_Long:
   202                 pool[i] = new CONSTANT_Long_info(cr);
   203                 i++;
   204                 break;
   206             case CONSTANT_MethodHandle:
   207                 pool[i] = new CONSTANT_MethodHandle_info(this, cr);
   208                 break;
   210             case CONSTANT_MethodType:
   211                 pool[i] = new CONSTANT_MethodType_info(this, cr);
   212                 break;
   214             case CONSTANT_Methodref:
   215                 pool[i] = new CONSTANT_Methodref_info(this, cr);
   216                 break;
   218             case CONSTANT_NameAndType:
   219                 pool[i] = new CONSTANT_NameAndType_info(this, cr);
   220                 break;
   222             case CONSTANT_String:
   223                 pool[i] = new CONSTANT_String_info(this, cr);
   224                 break;
   226             case CONSTANT_Utf8:
   227                 pool[i] = new CONSTANT_Utf8_info(cr);
   228                 break;
   230             default:
   231                 throw new InvalidEntry(i, tag);
   232             }
   233         }
   234     }
   236     public ConstantPool(CPInfo[] pool) {
   237         this.pool = pool;
   238     }
   240     public int size() {
   241         return pool.length;
   242     }
   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     }
   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     }
   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     }
   273     public CONSTANT_Utf8_info getUTF8Info(int index) throws InvalidIndex, UnexpectedEntry {
   274         return ((CONSTANT_Utf8_info) get(index, CONSTANT_Utf8));
   275     }
   277     public CONSTANT_Class_info getClassInfo(int index) throws InvalidIndex, UnexpectedEntry {
   278         return ((CONSTANT_Class_info) get(index, CONSTANT_Class));
   279     }
   281     public CONSTANT_NameAndType_info getNameAndTypeInfo(int index) throws InvalidIndex, UnexpectedEntry {
   282         return ((CONSTANT_NameAndType_info) get(index, CONSTANT_NameAndType));
   283     }
   285     public String getUTF8Value(int index) throws InvalidIndex, UnexpectedEntry {
   286         return getUTF8Info(index).value;
   287     }
   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     }
   299     public Iterable<CPInfo> entries() {
   300         return new Iterable<CPInfo>() {
   301             public Iterator<CPInfo> iterator() {
   302                 return new Iterator<CPInfo>() {
   304                     public boolean hasNext() {
   305                         return next < pool.length;
   306                     }
   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                     }
   321                     public void remove() {
   322                         throw new UnsupportedOperationException();
   323                     }
   325                     private CPInfo current;
   326                     private int next = 1;
   328                 };
   329             }
   330         };
   331     }
   333     private CPInfo[] pool;
   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     }
   352     public static abstract class CPInfo {
   353         CPInfo() {
   354             this.cp = null;
   355         }
   357         CPInfo(ConstantPool cp) {
   358             this.cp = cp;
   359         }
   361         public abstract int getTag();
   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         }
   369         public abstract int byteLength();
   371         public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
   373         protected final ConstantPool cp;
   374     }
   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         }
   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         }
   391         public int getTag() {
   392             return tag;
   393         }
   395         public int byteLength() {
   396             return 5;
   397         }
   399         public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
   400             return cp.getClassInfo(class_index);
   401         }
   403         public String getClassName() throws ConstantPoolException {
   404             return cp.getClassInfo(class_index).getName();
   405         }
   407         public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
   408             return cp.getNameAndTypeInfo(name_and_type_index);
   409         }
   411         public final int tag;
   412         public final int class_index;
   413         public final int name_and_type_index;
   414     }
   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         }
   422         public CONSTANT_Class_info(ConstantPool cp, int name_index) {
   423             super(cp);
   424             this.name_index = name_index;
   425         }
   427         public int getTag() {
   428             return CONSTANT_Class;
   429         }
   431         public int  byteLength() {
   432             return 3;
   433         }
   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         }
   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         }
   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         }
   472         @Override
   473         public String toString() {
   474             return "CONSTANT_Class_info[name_index: " + name_index + "]";
   475         }
   477         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   478             return visitor.visitClass(this, data);
   479         }
   481         public final int name_index;
   482     }
   484     public static class CONSTANT_Double_info extends CPInfo {
   485         CONSTANT_Double_info(ClassReader cr) throws IOException {
   486             value = cr.readDouble();
   487         }
   489         public CONSTANT_Double_info(double value) {
   490             this.value = value;
   491         }
   493         public int getTag() {
   494             return CONSTANT_Double;
   495         }
   497         public int  byteLength() {
   498             return 9;
   499         }
   501         @Override
   502         public int size() {
   503             return 2;
   504         }
   506         @Override
   507         public String toString() {
   508             return "CONSTANT_Double_info[value: " + value + "]";
   509         }
   511         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   512             return visitor.visitDouble(this, data);
   513         }
   515         public final double value;
   516     }
   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         }
   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         }
   527         @Override
   528         public String toString() {
   529             return "CONSTANT_Fieldref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
   530         }
   532         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   533             return visitor.visitFieldref(this, data);
   534         }
   535     }
   537     public static class CONSTANT_Float_info extends CPInfo {
   538         CONSTANT_Float_info(ClassReader cr) throws IOException {
   539             value = cr.readFloat();
   540         }
   542         public CONSTANT_Float_info(float value) {
   543             this.value = value;
   544         }
   546         public int getTag() {
   547             return CONSTANT_Float;
   548         }
   550         public int byteLength() {
   551             return 5;
   552         }
   554         @Override
   555         public String toString() {
   556             return "CONSTANT_Float_info[value: " + value + "]";
   557         }
   559         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   560             return visitor.visitFloat(this, data);
   561         }
   563         public final float value;
   564     }
   566     public static class CONSTANT_Integer_info extends CPInfo {
   567         CONSTANT_Integer_info(ClassReader cr) throws IOException {
   568             value = cr.readInt();
   569         }
   571         public CONSTANT_Integer_info(int value) {
   572             this.value = value;
   573         }
   575         public int getTag() {
   576             return CONSTANT_Integer;
   577         }
   579         public int byteLength() {
   580             return 5;
   581         }
   583         @Override
   584         public String toString() {
   585             return "CONSTANT_Integer_info[value: " + value + "]";
   586         }
   588         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   589             return visitor.visitInteger(this, data);
   590         }
   592         public final int value;
   593     }
   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         }
   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         }
   604         @Override
   605         public String toString() {
   606             return "CONSTANT_InterfaceMethodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
   607         }
   609         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   610             return visitor.visitInterfaceMethodref(this, data);
   611         }
   612     }
   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         }
   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         }
   627         public int getTag() {
   628             return CONSTANT_InvokeDynamic;
   629         }
   631         public int byteLength() {
   632             return 5;
   633         }
   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         }
   640         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   641             return visitor.visitInvokeDynamic(this, data);
   642         }
   644         public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
   645             return cp.getNameAndTypeInfo(name_and_type_index);
   646         }
   648         public final int bootstrap_method_attr_index;
   649         public final int name_and_type_index;
   650     }
   652     public static class CONSTANT_Long_info extends CPInfo {
   653         CONSTANT_Long_info(ClassReader cr) throws IOException {
   654             value = cr.readLong();
   655         }
   657         public CONSTANT_Long_info(long value) {
   658             this.value = value;
   659         }
   661         public int getTag() {
   662             return CONSTANT_Long;
   663         }
   665         @Override
   666         public int size() {
   667             return 2;
   668         }
   670         public int byteLength() {
   671             return 9;
   672         }
   674         @Override
   675         public String toString() {
   676             return "CONSTANT_Long_info[value: " + value + "]";
   677         }
   679         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   680             return visitor.visitLong(this, data);
   681         }
   683         public final long value;
   684     }
   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         }
   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         }
   699         public int getTag() {
   700             return CONSTANT_MethodHandle;
   701         }
   703         public int byteLength() {
   704             return 4;
   705         }
   707         @Override
   708         public String toString() {
   709             return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]";
   710         }
   712         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   713             return visitor.visitMethodHandle(this, data);
   714         }
   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         }
   728         public final RefKind reference_kind;
   729         public final int reference_index;
   730     }
   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         }
   738         public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) {
   739             super(cp);
   740             this.descriptor_index = signature_index;
   741         }
   743         public int getTag() {
   744             return CONSTANT_MethodType;
   745         }
   747         public int byteLength() {
   748             return 3;
   749         }
   751         @Override
   752         public String toString() {
   753             return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]";
   754         }
   756         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   757             return visitor.visitMethodType(this, data);
   758         }
   760         public String getType() throws ConstantPoolException {
   761             return cp.getUTF8Value(descriptor_index);
   762         }
   764         public final int descriptor_index;
   765     }
   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         }
   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         }
   776         @Override
   777         public String toString() {
   778             return "CONSTANT_Methodref_info[class_index: " + class_index + ", name_and_type_index: " + name_and_type_index + "]";
   779         }
   781         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   782             return visitor.visitMethodref(this, data);
   783         }
   784     }
   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         }
   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         }
   799         public int getTag() {
   800             return CONSTANT_NameAndType;
   801         }
   803         public int byteLength() {
   804             return 5;
   805         }
   807         public String getName() throws ConstantPoolException {
   808             return cp.getUTF8Value(name_index);
   809         }
   811         public String getType() throws ConstantPoolException {
   812             return cp.getUTF8Value(type_index);
   813         }
   815         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   816             return visitor.visitNameAndType(this, data);
   817         }
   819         @Override
   820         public String toString() {
   821             return "CONSTANT_NameAndType_info[name_index: " + name_index + ", type_index: " + type_index + "]";
   822         }
   824         public final int name_index;
   825         public final int type_index;
   826     }
   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         }
   834         public CONSTANT_String_info(ConstantPool cp, int string_index) {
   835             super(cp);
   836             this.string_index = string_index;
   837         }
   839         public int getTag() {
   840             return CONSTANT_String;
   841         }
   843         public int byteLength() {
   844             return 3;
   845         }
   847         public String getString() throws ConstantPoolException {
   848             return cp.getUTF8Value(string_index);
   849         }
   851         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   852             return visitor.visitString(this, data);
   853         }
   855         @Override
   856         public String toString() {
   857             return "CONSTANT_String_info[class_index: " + string_index + "]";
   858         }
   860         public final int string_index;
   861     }
   863     public static class CONSTANT_Utf8_info extends CPInfo {
   864         CONSTANT_Utf8_info(ClassReader cr) throws IOException {
   865             value = cr.readUTF();
   866         }
   868         public CONSTANT_Utf8_info(String value) {
   869             this.value = value;
   870         }
   872         public int getTag() {
   873             return CONSTANT_Utf8;
   874         }
   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         }
   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         }
   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         }
   907         public <R, D> R accept(Visitor<R, D> visitor, D data) {
   908             return visitor.visitUtf8(this, data);
   909         }
   911         public final String value;
   912     }
   914 }

mercurial