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

Tue, 03 Jun 2008 13:26:47 -0700

author
jjg
date
Tue, 03 Jun 2008 13:26:47 -0700
changeset 46
7708bd6d800d
child 282
fc634a593812
permissions
-rw-r--r--

4075303: Use javap to enquire aboput a specific inner class
4348375: Javap is not internationalized
4459541: "javap -l" shows line numbers as signed short; they should be unsigned
4501660: change diagnostic of -help as 'print this help message and exit'
4776241: unused source file in javap...
4870651: javap should recognize generics, varargs, enum
4876942: javap invoked without args does not print help screen
4880663: javap could output whitespace between class name and opening brace
4975569: javap doesn't print new flag bits
6271787: javap dumps LocalVariableTypeTable attribute in hex, needs to print a table
6305779: javap: support annotations
6439940: Clean up javap implementation
6469569: wrong check of searchpath in JavapEnvironment
6474890: javap does not open .zip files in -classpath
6587786: Javap throws error : "ERROR:Could not find <classname>" for JRE classes
6622215: javap ignores certain relevant access flags
6622216: javap names some attributes incorrectly
6622232: javap gets whitespace confused
6622260: javap prints negative bytes incorrectly in hex
Reviewed-by: ksrini

     1 /*
     2  * Copyright 2008 Sun Microsystems, Inc.  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.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.classfile;
    28 import java.io.ByteArrayOutputStream;
    29 import java.io.DataOutputStream;
    30 import java.io.File;
    31 import java.io.FileOutputStream;
    32 import java.io.IOException;
    33 import java.io.OutputStream;
    35 import static com.sun.tools.classfile.Annotation.*;
    36 import static com.sun.tools.classfile.ConstantPool.*;
    37 import static com.sun.tools.classfile.StackMapTable_attribute.*;
    38 import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
    40 /**
    41  * Write a ClassFile data structure to a file or stream.
    42  *
    43  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    44  *  you write code that depends on this, you do so at your own risk.
    45  *  This code and its internal interfaces are subject to change or
    46  *  deletion without notice.</b>
    47  */
    48 public class ClassWriter {
    49     public ClassWriter() {
    50         attributeWriter = new AttributeWriter();
    51         constantPoolWriter = new ConstantPoolWriter();
    52         out = new ClassOutputStream();
    53     }
    55     /**
    56      * Write a ClassFile data structure to a file.
    57      */
    58     public void write(ClassFile classFile, File f) throws IOException {
    59         FileOutputStream f_out = new FileOutputStream(f);
    60         try {
    61             write(classFile, f_out);
    62         } finally {
    63             f_out.close();
    64         }
    65     }
    67     /**
    68      * Write a ClassFile data structure to a stream.
    69      */
    70     public void write(ClassFile classFile, OutputStream s) throws IOException {
    71         this.classFile = classFile;
    72         out.reset();
    73         write();
    74         out.writeTo(s);
    75     }
    77     protected void write() throws IOException {
    78         writeHeader();
    79         writeConstantPool();
    80         writeAccessFlags(classFile.access_flags);
    81         writeClassInfo();
    82         writeFields();
    83         writeMethods();
    84         writeAttributes(classFile.attributes);
    85     }
    87     protected void writeHeader() {
    88         out.writeInt(classFile.magic);
    89         out.writeShort(classFile.minor_version);
    90         out.writeShort(classFile.major_version);
    91     }
    93     protected void writeAccessFlags(AccessFlags flags) {
    94         out.writeShort(flags.flags);
    95     }
    97     protected void writeAttributes(Attributes attributes) {
    98         int size = attributes.size();
    99         out.writeShort(size);
   100         for (Attribute attr: attributes)
   101             attributeWriter.write(attr, out);
   102     }
   104     protected void writeClassInfo() {
   105         out.writeShort(classFile.this_class);
   106         out.writeShort(classFile.super_class);
   107         int[] interfaces = classFile.interfaces;
   108         out.writeShort(interfaces.length);
   109         for (int i: interfaces)
   110             out.writeShort(i);
   111     }
   113     protected void writeDescriptor(Descriptor d) {
   114         out.writeShort(d.index);
   115     }
   117     protected void writeConstantPool() {
   118         ConstantPool pool = classFile.constant_pool;
   119         int size = pool.size();
   120         out.writeShort(size);
   121         try {
   122             for (int i = 1; i < size; ) {
   123                 i += constantPoolWriter.write(pool.get(i), out);
   124             }
   125         } catch (ConstantPoolException e) {
   126             throw new Error(e); // ??
   127         }
   128     }
   130     protected void writeFields() throws IOException {
   131         Field[] fields = classFile.fields;
   132         out.writeShort(fields.length);
   133         for (Field f: fields)
   134             writeField(f);
   135     }
   137     protected void writeField(Field f) throws IOException {
   138         writeAccessFlags(f.access_flags);
   139         out.writeShort(f.name_index);
   140         writeDescriptor(f.descriptor);
   141         writeAttributes(f.attributes);
   142     }
   144     protected void writeMethods() throws IOException {
   145         Method[] methods = classFile.methods;
   146         out.writeShort(methods.length);
   147         for (Method m: methods) {
   148             writeMethod(m);
   149         }
   150     }
   152     protected void writeMethod(Method m) throws IOException {
   153         writeAccessFlags(m.access_flags);
   154         out.writeShort(m.name_index);
   155         writeDescriptor(m.descriptor);
   156         writeAttributes(m.attributes);
   157     }
   159     protected ClassFile classFile;
   160     protected ClassOutputStream out;
   161     protected AttributeWriter attributeWriter;
   162     protected ConstantPoolWriter constantPoolWriter;
   164     /**
   165      * Subtype of ByteArrayOutputStream with the convenience methods of
   166      * a DataOutputStream. Since ByteArrayOutputStream does not throw
   167      * IOException, there are no exceptions from the additional
   168      * convenience methods either,
   169      */
   170     protected static class ClassOutputStream extends ByteArrayOutputStream {
   171         public ClassOutputStream() {
   172             d = new DataOutputStream(this);
   173         }
   175         public void writeByte(int value) {
   176             try {
   177                 d.writeByte(value);
   178             } catch (IOException ignore) {
   179             }
   180         }
   182         public void writeShort(int value) {
   183             try {
   184                 d.writeShort(value);
   185             } catch (IOException ignore) {
   186             }
   187         }
   189         public void writeInt(int value) {
   190             try {
   191                 d.writeInt(value);
   192             } catch (IOException ignore) {
   193             }
   194         }
   196         public void writeLong(long value) {
   197             try {
   198                 d.writeLong(value);
   199             } catch (IOException ignore) {
   200             }
   201         }
   203         public void writeFloat(float value) {
   204             try {
   205                 d.writeFloat(value);
   206             } catch (IOException ignore) {
   207             }
   208         }
   210         public void writeDouble(double value) {
   211             try {
   212                 d.writeDouble(value);
   213             } catch (IOException ignore) {
   214             }
   215         }
   217         public void writeUTF(String value) {
   218             try {
   219                 d.writeUTF(value);
   220             } catch (IOException ignore) {
   221             }
   222         }
   224         public void writeTo(ClassOutputStream s) {
   225             try {
   226                 super.writeTo(s);
   227             } catch (IOException ignore) {
   228             }
   229         }
   231         private DataOutputStream d;
   232     }
   234     /**
   235      * Writer for the entries in the constant pool.
   236      */
   237     protected static class ConstantPoolWriter
   238            implements ConstantPool.Visitor<Integer,ClassOutputStream> {
   239         protected int write(CPInfo info, ClassOutputStream out) {
   240             out.writeByte(info.getTag());
   241             return info.accept(this, out);
   242         }
   244         public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {
   245             out.writeShort(info.name_index);
   246             return 1;
   247         }
   249         public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {
   250             out.writeDouble(info.value);
   251             return 2;
   252         }
   254         public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {
   255             writeRef(info, out);
   256             return 1;
   257         }
   259         public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {
   260             out.writeFloat(info.value);
   261             return 1;
   262         }
   264         public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {
   265             out.writeInt(info.value);
   266             return 1;
   267         }
   269         public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {
   270             writeRef(info, out);
   271             return 1;
   272         }
   274         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
   275             out.writeLong(info.value);
   276             return 2;
   277         }
   279         public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {
   280             out.writeShort(info.name_index);
   281             out.writeShort(info.type_index);
   282             return 1;
   283         }
   285         public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
   286             return writeRef(info, out);
   287         }
   289         public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {
   290             out.writeShort(info.string_index);
   291             return 1;
   292         }
   294         public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {
   295             out.writeUTF(info.value);
   296             return 1;
   297         }
   299         protected Integer writeRef(CPRefInfo info, ClassOutputStream out) {
   300             out.writeShort(info.class_index);
   301             out.writeShort(info.name_and_type_index);
   302             return 1;
   303         }
   304     }
   306     /**
   307      * Writer for the different types of attribute.
   308      */
   309     protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> {
   310         public void write(Attributes attributes, ClassOutputStream out) {
   311             int size = attributes.size();
   312             out.writeShort(size);
   313             for (Attribute a: attributes)
   314                 write(a, out);
   315         }
   317         // Note: due to the use of shared resources, this method is not reentrant.
   318         public void write(Attribute attr, ClassOutputStream out) {
   319             out.writeShort(attr.attribute_name_index);
   320             sharedOut.reset();
   321             attr.accept(this, sharedOut);
   322             out.writeInt(sharedOut.size());
   323             sharedOut.writeTo(out);
   324         }
   326         protected ClassOutputStream sharedOut = new ClassOutputStream();
   327         protected AnnotationWriter annotationWriter = new AnnotationWriter();
   329         public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {
   330             out.write(attr.info, 0, attr.info.length);
   331             return null;
   332         }
   334         public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {
   335             annotationWriter.write(attr.default_value, out);
   336             return null;
   337         }
   339         public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
   340             out.writeShort(attr.character_range_table.length);
   341             for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
   342                 writeCharacterRangeTableEntry(e, out);
   343             return null;
   344         }
   346         protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) {
   347             out.writeShort(entry.start_pc);
   348             out.writeShort(entry.end_pc);
   349             out.writeInt(entry.character_range_start);
   350             out.writeInt(entry.character_range_end);
   351             out.writeShort(entry.flags);
   352         }
   354         public Void visitCode(Code_attribute attr, ClassOutputStream out) {
   355             out.writeShort(attr.max_stack);
   356             out.writeShort(attr.max_locals);
   357             out.writeInt(attr.code.length);
   358             out.write(attr.code, 0, attr.code.length);
   359             out.writeShort(attr.exception_table.length);
   360             for (Code_attribute.Exception_data e: attr.exception_table)
   361                 writeExceptionTableEntry(e, out);
   362             new AttributeWriter().write(attr.attributes, out);
   363             return null;
   364         }
   366         protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) {
   367             out.writeShort(exception_data.start_pc);
   368             out.writeShort(exception_data.end_pc);
   369             out.writeShort(exception_data.handler_pc);
   370             out.writeShort(exception_data.catch_type);
   371         }
   373         public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {
   374             out.writeShort(attr.compilationID_index);
   375             return null;
   376         }
   378         public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {
   379             out.writeShort(attr.constantvalue_index);
   380             return null;
   381         }
   383         public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {
   384             return null;
   385         }
   387         public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {
   388             out.writeShort(attr.class_index);
   389             out.writeShort(attr.method_index);
   390             return null;
   391         }
   393         public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {
   394             out.writeShort(attr.exception_index_table.length);
   395             for (int i: attr.exception_index_table)
   396                 out.writeShort(i);
   397             return null;
   398         }
   400         public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {
   401             out.writeShort(attr.classes.length);
   402             for (InnerClasses_attribute.Info info: attr.classes)
   403                 writeInnerClassesInfo(info, out);
   404             return null;
   405         }
   407         protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {
   408             out.writeShort(info.inner_class_info_index);
   409             out.writeShort(info.outer_class_info_index);
   410             out.writeShort(info.inner_name_index);
   411             writeAccessFlags(info.inner_class_access_flags, out);
   412         }
   414         public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {
   415             out.writeShort(attr.line_number_table.length);
   416             for (LineNumberTable_attribute.Entry e: attr.line_number_table)
   417                 writeLineNumberTableEntry(e, out);
   418             return null;
   419         }
   421         protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) {
   422             out.writeShort(entry.start_pc);
   423             out.writeShort(entry.line_number);
   424         }
   426         public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {
   427             out.writeShort(attr.local_variable_table.length);
   428             for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)
   429                 writeLocalVariableTableEntry(e, out);
   430             return null;
   431         }
   433         protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) {
   434             out.writeShort(entry.start_pc);
   435             out.writeShort(entry.length);
   436             out.writeShort(entry.name_index);
   437             out.writeShort(entry.descriptor_index);
   438             out.writeShort(entry.index);
   439         }
   441         public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {
   442             out.writeByte(attr.local_variable_table.length);
   443             for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)
   444                 writeLocalVariableTypeTableEntry(e, out);
   445             return null;
   446         }
   448         protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) {
   449             out.writeShort(entry.start_pc);
   450             out.writeShort(entry.length);
   451             out.writeShort(entry.name_index);
   452             out.writeShort(entry.signature_index);
   453             out.writeShort(entry.index);
   454         }
   456         public Void visitModule(Module_attribute attr, ClassOutputStream out) {
   457             out.writeShort(attr.module_name);
   458             return null;
   459         }
   461         public Void visitModuleExportTable(ModuleExportTable_attribute attr, ClassOutputStream out) {
   462             out.writeShort(attr.export_type_table.length);
   463             for (int i: attr.export_type_table)
   464                 out.writeShort(i);
   465             return null;
   466         }
   468         public Void visitModuleMemberTable(ModuleMemberTable_attribute attr, ClassOutputStream out) {
   469             out.writeShort(attr.package_member_table.length);
   470             for (int i: attr.package_member_table)
   471                 out.writeShort(i);
   472             return null;
   473         }
   475         public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
   476             annotationWriter.write(attr.annotations, out);
   477             return null;
   478         }
   480         public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
   481             annotationWriter.write(attr.annotations, out);
   482             return null;
   483         }
   485         public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   486             out.writeByte(attr.parameter_annotations.length);
   487             for (Annotation[] annos: attr.parameter_annotations)
   488                 annotationWriter.write(annos, out);
   489             return null;
   490         }
   492         public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
   493             out.writeByte(attr.parameter_annotations.length);
   494             for (Annotation[] annos: attr.parameter_annotations)
   495                 annotationWriter.write(annos, out);
   496             return null;
   497         }
   499         public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {
   500             out.writeShort(attr.signature_index);
   501             return null;
   502         }
   504         public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {
   505             out.write(attr.debug_extension, 0, attr.debug_extension.length);
   506             return null;
   507         }
   509         public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {
   510             out.writeShort(attr.sourcefile_index);
   511             return null;
   512         }
   514         public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {
   515             out.writeShort(attr.sourceID_index);
   516             return null;
   517         }
   519         public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {
   520             if (stackMapWriter == null)
   521                 stackMapWriter = new StackMapTableWriter();
   523             out.writeShort(attr.entries.length);
   524             for (stack_map_frame f: attr.entries)
   525                 stackMapWriter.write(f, out);
   526             return null;
   527         }
   529         public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {
   530             if (stackMapWriter == null)
   531                 stackMapWriter = new StackMapTableWriter();
   533             out.writeShort(attr.entries.length);
   534             for (stack_map_frame f: attr.entries)
   535                 stackMapWriter.write(f, out);
   536             return null;
   537         }
   539         public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {
   540             return null;
   541         }
   543         protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) {
   544             sharedOut.writeShort(flags.flags);
   545         }
   547         protected StackMapTableWriter stackMapWriter;
   548     }
   550     /**
   551      * Writer for the frames of StackMap and StackMapTable attributes.
   552      */
   553     protected static class StackMapTableWriter
   554             implements stack_map_frame.Visitor<Void,ClassOutputStream> {
   556         public void write(stack_map_frame frame, ClassOutputStream out) {
   557             out.write(frame.frame_type);
   558             frame.accept(this, out);
   559         }
   561         public Void visit_same_frame(same_frame frame, ClassOutputStream p) {
   562             return null;
   563         }
   565         public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {
   566             writeVerificationTypeInfo(frame.stack[0], out);
   567             return null;
   568         }
   570         public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {
   571             out.writeShort(frame.offset_delta);
   572             writeVerificationTypeInfo(frame.stack[0], out);
   573             return null;
   574         }
   576         public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {
   577             out.writeShort(frame.offset_delta);
   578             return null;
   579         }
   581         public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {
   582             out.writeShort(frame.offset_delta);
   583             return null;
   584         }
   586         public Void visit_append_frame(append_frame frame, ClassOutputStream out) {
   587             out.writeShort(frame.offset_delta);
   588             for (verification_type_info l: frame.locals)
   589                 writeVerificationTypeInfo(l, out);
   590             return null;
   591         }
   593         public Void visit_full_frame(full_frame frame, ClassOutputStream out) {
   594             out.writeShort(frame.offset_delta);
   595             out.writeShort(frame.locals.length);
   596             for (verification_type_info l: frame.locals)
   597                 writeVerificationTypeInfo(l, out);
   598             out.writeShort(frame.stack.length);
   599             for (verification_type_info s: frame.stack)
   600                 writeVerificationTypeInfo(s, out);
   601             return null;
   602         }
   604         protected void writeVerificationTypeInfo(verification_type_info info,
   605                 ClassOutputStream out)  {
   606             out.write(info.tag);
   607             switch (info.tag) {
   608             case ITEM_Top:
   609             case ITEM_Integer:
   610             case ITEM_Float:
   611             case ITEM_Long:
   612             case ITEM_Double:
   613             case ITEM_Null:
   614             case ITEM_UninitializedThis:
   615                 break;
   617             case ITEM_Object:
   618                 Object_variable_info o = (Object_variable_info) info;
   619                 out.writeShort(o.cpool_index);
   620                 break;
   622             case ITEM_Uninitialized:
   623                 Uninitialized_variable_info u = (Uninitialized_variable_info) info;
   624                 out.writeShort(u.offset);
   625                 break;
   627             default:
   628                 throw new Error();
   629             }
   630         }
   631     }
   633     /**
   634      * Writer for annotations and the values they contain.
   635      */
   636     protected static class AnnotationWriter
   637             implements Annotation.element_value.Visitor<Void,ClassOutputStream> {
   638         public void write(Annotation[] annos, ClassOutputStream out) {
   639             out.writeShort(annos.length);
   640             for (Annotation anno: annos)
   641                 write(anno, out);
   642         }
   644         public void write(Annotation anno, ClassOutputStream out) {
   645             out.writeShort(anno.type_index);
   646             out.writeShort(anno.element_value_pairs.length);
   647             for (element_value_pair p: anno.element_value_pairs)
   648                 write(p, out);
   649         }
   651         public void write(element_value_pair pair, ClassOutputStream out) {
   652             out.writeShort(pair.element_name_index);
   653             write(pair.value, out);
   654         }
   656         public void write(element_value ev, ClassOutputStream out) {
   657             out.writeByte(ev.tag);
   658             ev.accept(this, out);
   659         }
   661         public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {
   662             out.writeShort(ev.const_value_index);
   663             return null;
   664         }
   666         public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {
   667             out.writeShort(ev.type_name_index);
   668             out.writeShort(ev.const_name_index);
   669             return null;
   670         }
   672         public Void visitClass(Class_element_value ev, ClassOutputStream out) {
   673             out.writeShort(ev.class_info_index);
   674             return null;
   675         }
   677         public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {
   678             write(ev.annotation_value, out);
   679             return null;
   680         }
   682         public Void visitArray(Array_element_value ev, ClassOutputStream out) {
   683             out.writeShort(ev.num_values);
   684             for (element_value v: ev.values)
   685                 write(v, out);
   686             return null;
   687         }
   688     }
   689 }

mercurial