Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
41161 views
/*1* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526package com.sun.tools.classfile;2728import java.io.ByteArrayOutputStream;29import java.io.DataOutputStream;30import java.io.File;31import java.io.FileOutputStream;32import java.io.IOException;33import java.io.OutputStream;3435import static com.sun.tools.classfile.Annotation.*;36import static com.sun.tools.classfile.ConstantPool.*;37import static com.sun.tools.classfile.StackMapTable_attribute.*;38import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;3940/**41* Write a ClassFile data structure to a file or stream.42*43* <p><b>This is NOT part of any supported API.44* If 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 or46* deletion without notice.</b>47*/48public class ClassWriter {49public ClassWriter() {50attributeWriter = new AttributeWriter();51constantPoolWriter = new ConstantPoolWriter();52out = new ClassOutputStream();53}5455/**56* Write a ClassFile data structure to a file.57* @param classFile the classfile object to be written58* @param f the file59* @throws IOException if an error occurs while writing the file60*/61public void write(ClassFile classFile, File f) throws IOException {62try (FileOutputStream f_out = new FileOutputStream(f)) {63write(classFile, f_out);64}65}6667/**68* Write a ClassFile data structure to a stream.69* @param classFile the classfile object to be written70* @param s the stream71* @throws IOException if an error occurs while writing the file72*/73public void write(ClassFile classFile, OutputStream s) throws IOException {74this.classFile = classFile;75out.reset();76write();77out.writeTo(s);78}7980protected void write() throws IOException {81writeHeader();82writeConstantPool();83writeAccessFlags(classFile.access_flags);84writeClassInfo();85writeFields();86writeMethods();87writeAttributes(classFile.attributes);88}8990protected void writeHeader() {91out.writeInt(classFile.magic);92out.writeShort(classFile.minor_version);93out.writeShort(classFile.major_version);94}9596protected void writeAccessFlags(AccessFlags flags) {97out.writeShort(flags.flags);98}99100protected void writeAttributes(Attributes attributes) {101int size = attributes.size();102out.writeShort(size);103for (Attribute attr: attributes)104attributeWriter.write(attr, out);105}106107protected void writeClassInfo() {108out.writeShort(classFile.this_class);109out.writeShort(classFile.super_class);110int[] interfaces = classFile.interfaces;111out.writeShort(interfaces.length);112for (int i: interfaces)113out.writeShort(i);114}115116protected void writeDescriptor(Descriptor d) {117out.writeShort(d.index);118}119120protected void writeConstantPool() {121ConstantPool pool = classFile.constant_pool;122int size = pool.size();123out.writeShort(size);124for (CPInfo cpInfo: pool.entries())125constantPoolWriter.write(cpInfo, out);126}127128protected void writeFields() throws IOException {129Field[] fields = classFile.fields;130out.writeShort(fields.length);131for (Field f: fields)132writeField(f);133}134135protected void writeField(Field f) throws IOException {136writeAccessFlags(f.access_flags);137out.writeShort(f.name_index);138writeDescriptor(f.descriptor);139writeAttributes(f.attributes);140}141142protected void writeMethods() throws IOException {143Method[] methods = classFile.methods;144out.writeShort(methods.length);145for (Method m: methods) {146writeMethod(m);147}148}149150protected void writeMethod(Method m) throws IOException {151writeAccessFlags(m.access_flags);152out.writeShort(m.name_index);153writeDescriptor(m.descriptor);154writeAttributes(m.attributes);155}156157protected ClassFile classFile;158protected ClassOutputStream out;159protected AttributeWriter attributeWriter;160protected ConstantPoolWriter constantPoolWriter;161162/**163* Subtype of ByteArrayOutputStream with the convenience methods of164* a DataOutputStream. Since ByteArrayOutputStream does not throw165* IOException, there are no exceptions from the additional166* convenience methods either,167*/168protected static class ClassOutputStream extends ByteArrayOutputStream {169public ClassOutputStream() {170d = new DataOutputStream(this);171}172173public void writeByte(int value) {174try {175d.writeByte(value);176} catch (IOException ignore) {177}178}179180public void writeShort(int value) {181try {182d.writeShort(value);183} catch (IOException ignore) {184}185}186187public void writeInt(int value) {188try {189d.writeInt(value);190} catch (IOException ignore) {191}192}193194public void writeLong(long value) {195try {196d.writeLong(value);197} catch (IOException ignore) {198}199}200201public void writeFloat(float value) {202try {203d.writeFloat(value);204} catch (IOException ignore) {205}206}207208public void writeDouble(double value) {209try {210d.writeDouble(value);211} catch (IOException ignore) {212}213}214215public void writeUTF(String value) {216try {217d.writeUTF(value);218} catch (IOException ignore) {219}220}221222public void writeTo(ClassOutputStream s) {223try {224super.writeTo(s);225} catch (IOException ignore) {226}227}228229private final DataOutputStream d;230}231232/**233* Writer for the entries in the constant pool.234*/235protected static class ConstantPoolWriter236implements ConstantPool.Visitor<Integer,ClassOutputStream> {237protected int write(CPInfo info, ClassOutputStream out) {238out.writeByte(info.getTag());239return info.accept(this, out);240}241242@Override243public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) {244out.writeShort(info.name_index);245return 1;246}247248@Override249public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) {250out.writeDouble(info.value);251return 2;252}253254@Override255public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) {256writeRef(info, out);257return 1;258}259260@Override261public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) {262out.writeFloat(info.value);263return 1;264}265266@Override267public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) {268out.writeInt(info.value);269return 1;270}271272@Override273public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) {274writeRef(info, out);275return 1;276}277278@Override279public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) {280out.writeShort(info.bootstrap_method_attr_index);281out.writeShort(info.name_and_type_index);282return 1;283}284285public Integer visitDynamicConstant(CONSTANT_Dynamic_info info, ClassOutputStream out) {286out.writeShort(info.bootstrap_method_attr_index);287out.writeShort(info.name_and_type_index);288return 1;289}290291@Override292public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {293out.writeLong(info.value);294return 2;295}296297@Override298public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) {299out.writeByte(info.reference_kind.tag);300out.writeShort(info.reference_index);301return 1;302}303304@Override305public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) {306out.writeShort(info.descriptor_index);307return 1;308}309310@Override311public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {312return writeRef(info, out);313}314315@Override316public Integer visitModule(CONSTANT_Module_info info, ClassOutputStream out) {317out.writeShort(info.name_index);318return 1;319}320321@Override322public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) {323out.writeShort(info.name_index);324out.writeShort(info.type_index);325return 1;326}327328@Override329public Integer visitPackage(CONSTANT_Package_info info, ClassOutputStream out) {330out.writeShort(info.name_index);331return 1;332}333334@Override335public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) {336out.writeShort(info.string_index);337return 1;338}339340@Override341public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) {342out.writeUTF(info.value);343return 1;344}345346protected Integer writeRef(CPRefInfo info, ClassOutputStream out) {347out.writeShort(info.class_index);348out.writeShort(info.name_and_type_index);349return 1;350}351}352353/**354* Writer for the different types of attribute.355*/356protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> {357public void write(Attributes attributes, ClassOutputStream out) {358int size = attributes.size();359out.writeShort(size);360for (Attribute a: attributes)361write(a, out);362}363364public void write(Attribute attr, ClassOutputStream out) {365out.writeShort(attr.attribute_name_index);366ClassOutputStream nestedOut = new ClassOutputStream();367attr.accept(this, nestedOut);368out.writeInt(nestedOut.size());369nestedOut.writeTo(out);370}371372protected AnnotationWriter annotationWriter = new AnnotationWriter();373374@Override375public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) {376out.write(attr.info, 0, attr.info.length);377return null;378}379380@Override381public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) {382annotationWriter.write(attr.default_value, out);383return null;384}385386@Override387public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) {388out.writeShort(attr.bootstrap_method_specifiers.length);389for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) {390out.writeShort(bsm.bootstrap_method_ref);391int bsm_args_count = bsm.bootstrap_arguments.length;392out.writeShort(bsm_args_count);393for (int i : bsm.bootstrap_arguments) {394out.writeShort(i);395}396}397return null;398}399400@Override401public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {402out.writeShort(attr.character_range_table.length);403for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)404writeCharacterRangeTableEntry(e, out);405return null;406}407408protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) {409out.writeShort(entry.start_pc);410out.writeShort(entry.end_pc);411out.writeInt(entry.character_range_start);412out.writeInt(entry.character_range_end);413out.writeShort(entry.flags);414}415416@Override417public Void visitCode(Code_attribute attr, ClassOutputStream out) {418out.writeShort(attr.max_stack);419out.writeShort(attr.max_locals);420out.writeInt(attr.code.length);421out.write(attr.code, 0, attr.code.length);422out.writeShort(attr.exception_table.length);423for (Code_attribute.Exception_data e: attr.exception_table)424writeExceptionTableEntry(e, out);425new AttributeWriter().write(attr.attributes, out);426return null;427}428429protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) {430out.writeShort(exception_data.start_pc);431out.writeShort(exception_data.end_pc);432out.writeShort(exception_data.handler_pc);433out.writeShort(exception_data.catch_type);434}435436@Override437public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) {438out.writeShort(attr.compilationID_index);439return null;440}441442@Override443public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) {444out.writeShort(attr.constantvalue_index);445return null;446}447448@Override449public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) {450return null;451}452453@Override454public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) {455out.writeShort(attr.class_index);456out.writeShort(attr.method_index);457return null;458}459460@Override461public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) {462out.writeShort(attr.exception_index_table.length);463for (int i: attr.exception_index_table)464out.writeShort(i);465return null;466}467468@Override469public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) {470out.writeShort(attr.classes.length);471for (InnerClasses_attribute.Info info: attr.classes)472writeInnerClassesInfo(info, out);473return null;474}475476protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) {477out.writeShort(info.inner_class_info_index);478out.writeShort(info.outer_class_info_index);479out.writeShort(info.inner_name_index);480writeAccessFlags(info.inner_class_access_flags, out);481}482483@Override484public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) {485out.writeShort(attr.line_number_table.length);486for (LineNumberTable_attribute.Entry e: attr.line_number_table)487writeLineNumberTableEntry(e, out);488return null;489}490491protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) {492out.writeShort(entry.start_pc);493out.writeShort(entry.line_number);494}495496@Override497public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) {498out.writeShort(attr.local_variable_table.length);499for (LocalVariableTable_attribute.Entry e: attr.local_variable_table)500writeLocalVariableTableEntry(e, out);501return null;502}503504protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) {505out.writeShort(entry.start_pc);506out.writeShort(entry.length);507out.writeShort(entry.name_index);508out.writeShort(entry.descriptor_index);509out.writeShort(entry.index);510}511512@Override513public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) {514out.writeShort(attr.local_variable_table.length);515for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table)516writeLocalVariableTypeTableEntry(e, out);517return null;518}519520protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) {521out.writeShort(entry.start_pc);522out.writeShort(entry.length);523out.writeShort(entry.name_index);524out.writeShort(entry.signature_index);525out.writeShort(entry.index);526}527528@Override529public Void visitNestHost(NestHost_attribute attr, ClassOutputStream out) {530out.writeShort(attr.top_index);531return null;532}533534@Override535public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {536out.writeByte(attr.method_parameter_table.length);537for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {538out.writeShort(e.name_index);539out.writeShort(e.flags);540}541return null;542}543544@Override545public Void visitModule(Module_attribute attr, ClassOutputStream out) {546out.writeShort(attr.module_name);547out.writeShort(attr.module_flags);548out.writeShort(attr.module_version_index);549550out.writeShort(attr.requires.length);551for (Module_attribute.RequiresEntry e: attr.requires) {552out.writeShort(e.requires_index);553out.writeShort(e.requires_flags);554out.writeShort(e.requires_version_index);555}556557out.writeShort(attr.exports.length);558for (Module_attribute.ExportsEntry e: attr.exports) {559out.writeShort(e.exports_index);560out.writeShort(e.exports_flags);561out.writeShort(e.exports_to_index.length);562for (int index: e.exports_to_index)563out.writeShort(index);564}565566out.writeShort(attr.opens.length);567for (Module_attribute.OpensEntry e: attr.opens) {568out.writeShort(e.opens_index);569out.writeShort(e.opens_flags);570out.writeShort(e.opens_to_index.length);571for (int index: e.opens_to_index)572out.writeShort(index);573}574575out.writeShort(attr.uses_index.length);576for (int index: attr.uses_index) {577out.writeShort(index);578}579580out.writeShort(attr.provides.length);581for (Module_attribute.ProvidesEntry e: attr.provides) {582out.writeShort(e.provides_index);583out.writeShort(e.with_count);584for (int with : e.with_index) {585out.writeShort(with);586}587}588589return null;590}591592@Override593public Void visitModuleHashes(ModuleHashes_attribute attr, ClassOutputStream out) {594out.writeShort(attr.algorithm_index);595out.writeShort(attr.hashes_table.length);596for (ModuleHashes_attribute.Entry e: attr.hashes_table) {597out.writeShort(e.module_name_index);598out.writeShort(e.hash.length);599for (byte b: e.hash) {600out.writeByte(b);601}602}603return null;604}605606@Override607public Void visitModuleMainClass(ModuleMainClass_attribute attr, ClassOutputStream out) {608out.writeShort(attr.main_class_index);609return null;610}611612@Override613public Void visitModulePackages(ModulePackages_attribute attr, ClassOutputStream out) {614out.writeShort(attr.packages_count);615for (int i: attr.packages_index)616out.writeShort(i);617return null;618}619620@Override621public Void visitModuleResolution(ModuleResolution_attribute attr, ClassOutputStream out) {622out.writeShort(attr.resolution_flags);623return null;624}625626@Override627public Void visitModuleTarget(ModuleTarget_attribute attr, ClassOutputStream out) {628out.writeShort(attr.target_platform_index);629return null;630}631632@Override633public Void visitNestMembers(NestMembers_attribute attr, ClassOutputStream out) {634out.writeShort(attr.members_indexes.length);635for (int i : attr.members_indexes) {636out.writeShort(i);637}638return null;639}640641@Override642public Void visitRecord(Record_attribute attr, ClassOutputStream out) {643out.writeShort(attr.component_count);644for (Record_attribute.ComponentInfo info: attr.component_info_arr) {645out.writeShort(info.name_index);646out.writeShort(info.descriptor.index);647int size = info.attributes.size();648out.writeShort(size);649for (Attribute componentAttr: info.attributes)650write(componentAttr, out);651}652return null;653}654655@Override656public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {657annotationWriter.write(attr.annotations, out);658return null;659}660661@Override662public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) {663out.writeByte(attr.parameter_annotations.length);664for (Annotation[] annos: attr.parameter_annotations)665annotationWriter.write(annos, out);666return null;667}668669@Override670public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {671annotationWriter.write(attr.annotations, out);672return null;673}674675@Override676public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {677annotationWriter.write(attr.annotations, out);678return null;679}680681@Override682public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {683out.writeByte(attr.parameter_annotations.length);684for (Annotation[] annos: attr.parameter_annotations)685annotationWriter.write(annos, out);686return null;687}688689@Override690public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {691annotationWriter.write(attr.annotations, out);692return null;693}694695@Override696public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, ClassOutputStream out) {697int n = attr.subtypes.length;698out.writeShort(n);699for (int i = 0 ; i < n ; i++) {700out.writeShort(attr.subtypes[i]);701}702return null;703}704705@Override706public Void visitSignature(Signature_attribute attr, ClassOutputStream out) {707out.writeShort(attr.signature_index);708return null;709}710711@Override712public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) {713out.write(attr.debug_extension, 0, attr.debug_extension.length);714return null;715}716717@Override718public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) {719out.writeShort(attr.sourcefile_index);720return null;721}722723@Override724public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) {725out.writeShort(attr.sourceID_index);726return null;727}728729@Override730public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) {731if (stackMapWriter == null)732stackMapWriter = new StackMapTableWriter();733734out.writeShort(attr.entries.length);735for (stack_map_frame f: attr.entries)736stackMapWriter.write(f, out);737return null;738}739740@Override741public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) {742if (stackMapWriter == null)743stackMapWriter = new StackMapTableWriter();744745out.writeShort(attr.entries.length);746for (stack_map_frame f: attr.entries)747stackMapWriter.write(f, out);748return null;749}750751@Override752public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) {753return null;754}755756protected void writeAccessFlags(AccessFlags flags, ClassOutputStream out) {757out.writeShort(flags.flags);758}759760protected StackMapTableWriter stackMapWriter;761}762763/**764* Writer for the frames of StackMap and StackMapTable attributes.765*/766protected static class StackMapTableWriter767implements stack_map_frame.Visitor<Void,ClassOutputStream> {768769public void write(stack_map_frame frame, ClassOutputStream out) {770out.write(frame.frame_type);771frame.accept(this, out);772}773774@Override775public Void visit_same_frame(same_frame frame, ClassOutputStream p) {776return null;777}778779@Override780public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) {781writeVerificationTypeInfo(frame.stack[0], out);782return null;783}784785@Override786public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) {787out.writeShort(frame.offset_delta);788writeVerificationTypeInfo(frame.stack[0], out);789return null;790}791792@Override793public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) {794out.writeShort(frame.offset_delta);795return null;796}797798@Override799public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) {800out.writeShort(frame.offset_delta);801return null;802}803804@Override805public Void visit_append_frame(append_frame frame, ClassOutputStream out) {806out.writeShort(frame.offset_delta);807for (verification_type_info l: frame.locals)808writeVerificationTypeInfo(l, out);809return null;810}811812@Override813public Void visit_full_frame(full_frame frame, ClassOutputStream out) {814out.writeShort(frame.offset_delta);815out.writeShort(frame.locals.length);816for (verification_type_info l: frame.locals)817writeVerificationTypeInfo(l, out);818out.writeShort(frame.stack.length);819for (verification_type_info s: frame.stack)820writeVerificationTypeInfo(s, out);821return null;822}823824protected void writeVerificationTypeInfo(verification_type_info info,825ClassOutputStream out) {826out.write(info.tag);827switch (info.tag) {828case ITEM_Top:829case ITEM_Integer:830case ITEM_Float:831case ITEM_Long:832case ITEM_Double:833case ITEM_Null:834case ITEM_UninitializedThis:835break;836837case ITEM_Object:838Object_variable_info o = (Object_variable_info) info;839out.writeShort(o.cpool_index);840break;841842case ITEM_Uninitialized:843Uninitialized_variable_info u = (Uninitialized_variable_info) info;844out.writeShort(u.offset);845break;846847default:848throw new Error();849}850}851}852853/**854* Writer for annotations and the values they contain.855*/856protected static class AnnotationWriter857implements Annotation.element_value.Visitor<Void,ClassOutputStream> {858public void write(Annotation[] annos, ClassOutputStream out) {859out.writeShort(annos.length);860for (Annotation anno: annos)861write(anno, out);862}863864public void write(TypeAnnotation[] annos, ClassOutputStream out) {865out.writeShort(annos.length);866for (TypeAnnotation anno: annos)867write(anno, out);868}869870public void write(Annotation anno, ClassOutputStream out) {871out.writeShort(anno.type_index);872out.writeShort(anno.element_value_pairs.length);873for (element_value_pair p: anno.element_value_pairs)874write(p, out);875}876877public void write(TypeAnnotation anno, ClassOutputStream out) {878write(anno.position, out);879write(anno.annotation, out);880}881882public void write(element_value_pair pair, ClassOutputStream out) {883out.writeShort(pair.element_name_index);884write(pair.value, out);885}886887public void write(element_value ev, ClassOutputStream out) {888out.writeByte(ev.tag);889ev.accept(this, out);890}891892@Override893public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) {894out.writeShort(ev.const_value_index);895return null;896}897898@Override899public Void visitEnum(Enum_element_value ev, ClassOutputStream out) {900out.writeShort(ev.type_name_index);901out.writeShort(ev.const_name_index);902return null;903}904905@Override906public Void visitClass(Class_element_value ev, ClassOutputStream out) {907out.writeShort(ev.class_info_index);908return null;909}910911@Override912public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) {913write(ev.annotation_value, out);914return null;915}916917@Override918public Void visitArray(Array_element_value ev, ClassOutputStream out) {919out.writeShort(ev.num_values);920for (element_value v: ev.values)921write(v, out);922return null;923}924925// TODO: Move this to TypeAnnotation to be closer with similar logic?926private void write(TypeAnnotation.Position p, ClassOutputStream out) {927out.writeByte(p.type.targetTypeValue());928switch (p.type) {929// instanceof930case INSTANCEOF:931// new expression932case NEW:933// constructor/method reference receiver934case CONSTRUCTOR_REFERENCE:935case METHOD_REFERENCE:936out.writeShort(p.offset);937break;938// local variable939case LOCAL_VARIABLE:940// resource variable941case RESOURCE_VARIABLE:942int table_length = p.lvarOffset.length;943out.writeShort(table_length);944for (int i = 0; i < table_length; ++i) {945out.writeShort(1); // for table length946out.writeShort(p.lvarOffset[i]);947out.writeShort(p.lvarLength[i]);948out.writeShort(p.lvarIndex[i]);949}950break;951// exception parameter952case EXCEPTION_PARAMETER:953out.writeShort(p.exception_index);954break;955// method receiver956case METHOD_RECEIVER:957// Do nothing958break;959// type parameters960case CLASS_TYPE_PARAMETER:961case METHOD_TYPE_PARAMETER:962out.writeByte(p.parameter_index);963break;964// type parameters bounds965case CLASS_TYPE_PARAMETER_BOUND:966case METHOD_TYPE_PARAMETER_BOUND:967out.writeByte(p.parameter_index);968out.writeByte(p.bound_index);969break;970// class extends or implements clause971case CLASS_EXTENDS:972out.writeShort(p.type_index);973break;974// throws975case THROWS:976out.writeShort(p.type_index);977break;978// method parameter979case METHOD_FORMAL_PARAMETER:980out.writeByte(p.parameter_index);981break;982// type cast983case CAST:984// method/constructor/reference type argument985case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:986case METHOD_INVOCATION_TYPE_ARGUMENT:987case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:988case METHOD_REFERENCE_TYPE_ARGUMENT:989out.writeShort(p.offset);990out.writeByte(p.type_index);991break;992// We don't need to worry about these993case METHOD_RETURN:994case FIELD:995break;996case UNKNOWN:997throw new AssertionError("ClassWriter: UNKNOWN target type should never occur!");998default:999throw new AssertionError("ClassWriter: Unknown target type for position: " + p);1000}10011002{ // Append location data for generics/arrays.1003// TODO: check for overrun?1004out.writeByte((byte)p.location.size());1005for (int i : TypeAnnotation.Position.getBinaryFromTypePath(p.location))1006out.writeByte((byte)i);1007}1008}1009}1010}101110121013