1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/classfile/ClassWriter.java Tue Jun 03 13:26:47 2008 -0700 1.3 @@ -0,0 +1,689 @@ 1.4 +/* 1.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Sun designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Sun in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.26 + * have any questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.classfile; 1.30 + 1.31 +import java.io.ByteArrayOutputStream; 1.32 +import java.io.DataOutputStream; 1.33 +import java.io.File; 1.34 +import java.io.FileOutputStream; 1.35 +import java.io.IOException; 1.36 +import java.io.OutputStream; 1.37 + 1.38 +import static com.sun.tools.classfile.Annotation.*; 1.39 +import static com.sun.tools.classfile.ConstantPool.*; 1.40 +import static com.sun.tools.classfile.StackMapTable_attribute.*; 1.41 +import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*; 1.42 + 1.43 +/** 1.44 + * Write a ClassFile data structure to a file or stream. 1.45 + * 1.46 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.47 + * you write code that depends on this, you do so at your own risk. 1.48 + * This code and its internal interfaces are subject to change or 1.49 + * deletion without notice.</b> 1.50 + */ 1.51 +public class ClassWriter { 1.52 + public ClassWriter() { 1.53 + attributeWriter = new AttributeWriter(); 1.54 + constantPoolWriter = new ConstantPoolWriter(); 1.55 + out = new ClassOutputStream(); 1.56 + } 1.57 + 1.58 + /** 1.59 + * Write a ClassFile data structure to a file. 1.60 + */ 1.61 + public void write(ClassFile classFile, File f) throws IOException { 1.62 + FileOutputStream f_out = new FileOutputStream(f); 1.63 + try { 1.64 + write(classFile, f_out); 1.65 + } finally { 1.66 + f_out.close(); 1.67 + } 1.68 + } 1.69 + 1.70 + /** 1.71 + * Write a ClassFile data structure to a stream. 1.72 + */ 1.73 + public void write(ClassFile classFile, OutputStream s) throws IOException { 1.74 + this.classFile = classFile; 1.75 + out.reset(); 1.76 + write(); 1.77 + out.writeTo(s); 1.78 + } 1.79 + 1.80 + protected void write() throws IOException { 1.81 + writeHeader(); 1.82 + writeConstantPool(); 1.83 + writeAccessFlags(classFile.access_flags); 1.84 + writeClassInfo(); 1.85 + writeFields(); 1.86 + writeMethods(); 1.87 + writeAttributes(classFile.attributes); 1.88 + } 1.89 + 1.90 + protected void writeHeader() { 1.91 + out.writeInt(classFile.magic); 1.92 + out.writeShort(classFile.minor_version); 1.93 + out.writeShort(classFile.major_version); 1.94 + } 1.95 + 1.96 + protected void writeAccessFlags(AccessFlags flags) { 1.97 + out.writeShort(flags.flags); 1.98 + } 1.99 + 1.100 + protected void writeAttributes(Attributes attributes) { 1.101 + int size = attributes.size(); 1.102 + out.writeShort(size); 1.103 + for (Attribute attr: attributes) 1.104 + attributeWriter.write(attr, out); 1.105 + } 1.106 + 1.107 + protected void writeClassInfo() { 1.108 + out.writeShort(classFile.this_class); 1.109 + out.writeShort(classFile.super_class); 1.110 + int[] interfaces = classFile.interfaces; 1.111 + out.writeShort(interfaces.length); 1.112 + for (int i: interfaces) 1.113 + out.writeShort(i); 1.114 + } 1.115 + 1.116 + protected void writeDescriptor(Descriptor d) { 1.117 + out.writeShort(d.index); 1.118 + } 1.119 + 1.120 + protected void writeConstantPool() { 1.121 + ConstantPool pool = classFile.constant_pool; 1.122 + int size = pool.size(); 1.123 + out.writeShort(size); 1.124 + try { 1.125 + for (int i = 1; i < size; ) { 1.126 + i += constantPoolWriter.write(pool.get(i), out); 1.127 + } 1.128 + } catch (ConstantPoolException e) { 1.129 + throw new Error(e); // ?? 1.130 + } 1.131 + } 1.132 + 1.133 + protected void writeFields() throws IOException { 1.134 + Field[] fields = classFile.fields; 1.135 + out.writeShort(fields.length); 1.136 + for (Field f: fields) 1.137 + writeField(f); 1.138 + } 1.139 + 1.140 + protected void writeField(Field f) throws IOException { 1.141 + writeAccessFlags(f.access_flags); 1.142 + out.writeShort(f.name_index); 1.143 + writeDescriptor(f.descriptor); 1.144 + writeAttributes(f.attributes); 1.145 + } 1.146 + 1.147 + protected void writeMethods() throws IOException { 1.148 + Method[] methods = classFile.methods; 1.149 + out.writeShort(methods.length); 1.150 + for (Method m: methods) { 1.151 + writeMethod(m); 1.152 + } 1.153 + } 1.154 + 1.155 + protected void writeMethod(Method m) throws IOException { 1.156 + writeAccessFlags(m.access_flags); 1.157 + out.writeShort(m.name_index); 1.158 + writeDescriptor(m.descriptor); 1.159 + writeAttributes(m.attributes); 1.160 + } 1.161 + 1.162 + protected ClassFile classFile; 1.163 + protected ClassOutputStream out; 1.164 + protected AttributeWriter attributeWriter; 1.165 + protected ConstantPoolWriter constantPoolWriter; 1.166 + 1.167 + /** 1.168 + * Subtype of ByteArrayOutputStream with the convenience methods of 1.169 + * a DataOutputStream. Since ByteArrayOutputStream does not throw 1.170 + * IOException, there are no exceptions from the additional 1.171 + * convenience methods either, 1.172 + */ 1.173 + protected static class ClassOutputStream extends ByteArrayOutputStream { 1.174 + public ClassOutputStream() { 1.175 + d = new DataOutputStream(this); 1.176 + } 1.177 + 1.178 + public void writeByte(int value) { 1.179 + try { 1.180 + d.writeByte(value); 1.181 + } catch (IOException ignore) { 1.182 + } 1.183 + } 1.184 + 1.185 + public void writeShort(int value) { 1.186 + try { 1.187 + d.writeShort(value); 1.188 + } catch (IOException ignore) { 1.189 + } 1.190 + } 1.191 + 1.192 + public void writeInt(int value) { 1.193 + try { 1.194 + d.writeInt(value); 1.195 + } catch (IOException ignore) { 1.196 + } 1.197 + } 1.198 + 1.199 + public void writeLong(long value) { 1.200 + try { 1.201 + d.writeLong(value); 1.202 + } catch (IOException ignore) { 1.203 + } 1.204 + } 1.205 + 1.206 + public void writeFloat(float value) { 1.207 + try { 1.208 + d.writeFloat(value); 1.209 + } catch (IOException ignore) { 1.210 + } 1.211 + } 1.212 + 1.213 + public void writeDouble(double value) { 1.214 + try { 1.215 + d.writeDouble(value); 1.216 + } catch (IOException ignore) { 1.217 + } 1.218 + } 1.219 + 1.220 + public void writeUTF(String value) { 1.221 + try { 1.222 + d.writeUTF(value); 1.223 + } catch (IOException ignore) { 1.224 + } 1.225 + } 1.226 + 1.227 + public void writeTo(ClassOutputStream s) { 1.228 + try { 1.229 + super.writeTo(s); 1.230 + } catch (IOException ignore) { 1.231 + } 1.232 + } 1.233 + 1.234 + private DataOutputStream d; 1.235 + } 1.236 + 1.237 + /** 1.238 + * Writer for the entries in the constant pool. 1.239 + */ 1.240 + protected static class ConstantPoolWriter 1.241 + implements ConstantPool.Visitor<Integer,ClassOutputStream> { 1.242 + protected int write(CPInfo info, ClassOutputStream out) { 1.243 + out.writeByte(info.getTag()); 1.244 + return info.accept(this, out); 1.245 + } 1.246 + 1.247 + public Integer visitClass(CONSTANT_Class_info info, ClassOutputStream out) { 1.248 + out.writeShort(info.name_index); 1.249 + return 1; 1.250 + } 1.251 + 1.252 + public Integer visitDouble(CONSTANT_Double_info info, ClassOutputStream out) { 1.253 + out.writeDouble(info.value); 1.254 + return 2; 1.255 + } 1.256 + 1.257 + public Integer visitFieldref(CONSTANT_Fieldref_info info, ClassOutputStream out) { 1.258 + writeRef(info, out); 1.259 + return 1; 1.260 + } 1.261 + 1.262 + public Integer visitFloat(CONSTANT_Float_info info, ClassOutputStream out) { 1.263 + out.writeFloat(info.value); 1.264 + return 1; 1.265 + } 1.266 + 1.267 + public Integer visitInteger(CONSTANT_Integer_info info, ClassOutputStream out) { 1.268 + out.writeInt(info.value); 1.269 + return 1; 1.270 + } 1.271 + 1.272 + public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ClassOutputStream out) { 1.273 + writeRef(info, out); 1.274 + return 1; 1.275 + } 1.276 + 1.277 + public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) { 1.278 + out.writeLong(info.value); 1.279 + return 2; 1.280 + } 1.281 + 1.282 + public Integer visitNameAndType(CONSTANT_NameAndType_info info, ClassOutputStream out) { 1.283 + out.writeShort(info.name_index); 1.284 + out.writeShort(info.type_index); 1.285 + return 1; 1.286 + } 1.287 + 1.288 + public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) { 1.289 + return writeRef(info, out); 1.290 + } 1.291 + 1.292 + public Integer visitString(CONSTANT_String_info info, ClassOutputStream out) { 1.293 + out.writeShort(info.string_index); 1.294 + return 1; 1.295 + } 1.296 + 1.297 + public Integer visitUtf8(CONSTANT_Utf8_info info, ClassOutputStream out) { 1.298 + out.writeUTF(info.value); 1.299 + return 1; 1.300 + } 1.301 + 1.302 + protected Integer writeRef(CPRefInfo info, ClassOutputStream out) { 1.303 + out.writeShort(info.class_index); 1.304 + out.writeShort(info.name_and_type_index); 1.305 + return 1; 1.306 + } 1.307 + } 1.308 + 1.309 + /** 1.310 + * Writer for the different types of attribute. 1.311 + */ 1.312 + protected static class AttributeWriter implements Attribute.Visitor<Void,ClassOutputStream> { 1.313 + public void write(Attributes attributes, ClassOutputStream out) { 1.314 + int size = attributes.size(); 1.315 + out.writeShort(size); 1.316 + for (Attribute a: attributes) 1.317 + write(a, out); 1.318 + } 1.319 + 1.320 + // Note: due to the use of shared resources, this method is not reentrant. 1.321 + public void write(Attribute attr, ClassOutputStream out) { 1.322 + out.writeShort(attr.attribute_name_index); 1.323 + sharedOut.reset(); 1.324 + attr.accept(this, sharedOut); 1.325 + out.writeInt(sharedOut.size()); 1.326 + sharedOut.writeTo(out); 1.327 + } 1.328 + 1.329 + protected ClassOutputStream sharedOut = new ClassOutputStream(); 1.330 + protected AnnotationWriter annotationWriter = new AnnotationWriter(); 1.331 + 1.332 + public Void visitDefault(DefaultAttribute attr, ClassOutputStream out) { 1.333 + out.write(attr.info, 0, attr.info.length); 1.334 + return null; 1.335 + } 1.336 + 1.337 + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, ClassOutputStream out) { 1.338 + annotationWriter.write(attr.default_value, out); 1.339 + return null; 1.340 + } 1.341 + 1.342 + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) { 1.343 + out.writeShort(attr.character_range_table.length); 1.344 + for (CharacterRangeTable_attribute.Entry e: attr.character_range_table) 1.345 + writeCharacterRangeTableEntry(e, out); 1.346 + return null; 1.347 + } 1.348 + 1.349 + protected void writeCharacterRangeTableEntry(CharacterRangeTable_attribute.Entry entry, ClassOutputStream out) { 1.350 + out.writeShort(entry.start_pc); 1.351 + out.writeShort(entry.end_pc); 1.352 + out.writeInt(entry.character_range_start); 1.353 + out.writeInt(entry.character_range_end); 1.354 + out.writeShort(entry.flags); 1.355 + } 1.356 + 1.357 + public Void visitCode(Code_attribute attr, ClassOutputStream out) { 1.358 + out.writeShort(attr.max_stack); 1.359 + out.writeShort(attr.max_locals); 1.360 + out.writeInt(attr.code.length); 1.361 + out.write(attr.code, 0, attr.code.length); 1.362 + out.writeShort(attr.exception_table.length); 1.363 + for (Code_attribute.Exception_data e: attr.exception_table) 1.364 + writeExceptionTableEntry(e, out); 1.365 + new AttributeWriter().write(attr.attributes, out); 1.366 + return null; 1.367 + } 1.368 + 1.369 + protected void writeExceptionTableEntry(Code_attribute.Exception_data exception_data, ClassOutputStream out) { 1.370 + out.writeShort(exception_data.start_pc); 1.371 + out.writeShort(exception_data.end_pc); 1.372 + out.writeShort(exception_data.handler_pc); 1.373 + out.writeShort(exception_data.catch_type); 1.374 + } 1.375 + 1.376 + public Void visitCompilationID(CompilationID_attribute attr, ClassOutputStream out) { 1.377 + out.writeShort(attr.compilationID_index); 1.378 + return null; 1.379 + } 1.380 + 1.381 + public Void visitConstantValue(ConstantValue_attribute attr, ClassOutputStream out) { 1.382 + out.writeShort(attr.constantvalue_index); 1.383 + return null; 1.384 + } 1.385 + 1.386 + public Void visitDeprecated(Deprecated_attribute attr, ClassOutputStream out) { 1.387 + return null; 1.388 + } 1.389 + 1.390 + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, ClassOutputStream out) { 1.391 + out.writeShort(attr.class_index); 1.392 + out.writeShort(attr.method_index); 1.393 + return null; 1.394 + } 1.395 + 1.396 + public Void visitExceptions(Exceptions_attribute attr, ClassOutputStream out) { 1.397 + out.writeShort(attr.exception_index_table.length); 1.398 + for (int i: attr.exception_index_table) 1.399 + out.writeShort(i); 1.400 + return null; 1.401 + } 1.402 + 1.403 + public Void visitInnerClasses(InnerClasses_attribute attr, ClassOutputStream out) { 1.404 + out.writeShort(attr.classes.length); 1.405 + for (InnerClasses_attribute.Info info: attr.classes) 1.406 + writeInnerClassesInfo(info, out); 1.407 + return null; 1.408 + } 1.409 + 1.410 + protected void writeInnerClassesInfo(InnerClasses_attribute.Info info, ClassOutputStream out) { 1.411 + out.writeShort(info.inner_class_info_index); 1.412 + out.writeShort(info.outer_class_info_index); 1.413 + out.writeShort(info.inner_name_index); 1.414 + writeAccessFlags(info.inner_class_access_flags, out); 1.415 + } 1.416 + 1.417 + public Void visitLineNumberTable(LineNumberTable_attribute attr, ClassOutputStream out) { 1.418 + out.writeShort(attr.line_number_table.length); 1.419 + for (LineNumberTable_attribute.Entry e: attr.line_number_table) 1.420 + writeLineNumberTableEntry(e, out); 1.421 + return null; 1.422 + } 1.423 + 1.424 + protected void writeLineNumberTableEntry(LineNumberTable_attribute.Entry entry, ClassOutputStream out) { 1.425 + out.writeShort(entry.start_pc); 1.426 + out.writeShort(entry.line_number); 1.427 + } 1.428 + 1.429 + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, ClassOutputStream out) { 1.430 + out.writeShort(attr.local_variable_table.length); 1.431 + for (LocalVariableTable_attribute.Entry e: attr.local_variable_table) 1.432 + writeLocalVariableTableEntry(e, out); 1.433 + return null; 1.434 + } 1.435 + 1.436 + protected void writeLocalVariableTableEntry(LocalVariableTable_attribute.Entry entry, ClassOutputStream out) { 1.437 + out.writeShort(entry.start_pc); 1.438 + out.writeShort(entry.length); 1.439 + out.writeShort(entry.name_index); 1.440 + out.writeShort(entry.descriptor_index); 1.441 + out.writeShort(entry.index); 1.442 + } 1.443 + 1.444 + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, ClassOutputStream out) { 1.445 + out.writeByte(attr.local_variable_table.length); 1.446 + for (LocalVariableTypeTable_attribute.Entry e: attr.local_variable_table) 1.447 + writeLocalVariableTypeTableEntry(e, out); 1.448 + return null; 1.449 + } 1.450 + 1.451 + protected void writeLocalVariableTypeTableEntry(LocalVariableTypeTable_attribute.Entry entry, ClassOutputStream out) { 1.452 + out.writeShort(entry.start_pc); 1.453 + out.writeShort(entry.length); 1.454 + out.writeShort(entry.name_index); 1.455 + out.writeShort(entry.signature_index); 1.456 + out.writeShort(entry.index); 1.457 + } 1.458 + 1.459 + public Void visitModule(Module_attribute attr, ClassOutputStream out) { 1.460 + out.writeShort(attr.module_name); 1.461 + return null; 1.462 + } 1.463 + 1.464 + public Void visitModuleExportTable(ModuleExportTable_attribute attr, ClassOutputStream out) { 1.465 + out.writeShort(attr.export_type_table.length); 1.466 + for (int i: attr.export_type_table) 1.467 + out.writeShort(i); 1.468 + return null; 1.469 + } 1.470 + 1.471 + public Void visitModuleMemberTable(ModuleMemberTable_attribute attr, ClassOutputStream out) { 1.472 + out.writeShort(attr.package_member_table.length); 1.473 + for (int i: attr.package_member_table) 1.474 + out.writeShort(i); 1.475 + return null; 1.476 + } 1.477 + 1.478 + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) { 1.479 + annotationWriter.write(attr.annotations, out); 1.480 + return null; 1.481 + } 1.482 + 1.483 + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) { 1.484 + annotationWriter.write(attr.annotations, out); 1.485 + return null; 1.486 + } 1.487 + 1.488 + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) { 1.489 + out.writeByte(attr.parameter_annotations.length); 1.490 + for (Annotation[] annos: attr.parameter_annotations) 1.491 + annotationWriter.write(annos, out); 1.492 + return null; 1.493 + } 1.494 + 1.495 + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, ClassOutputStream out) { 1.496 + out.writeByte(attr.parameter_annotations.length); 1.497 + for (Annotation[] annos: attr.parameter_annotations) 1.498 + annotationWriter.write(annos, out); 1.499 + return null; 1.500 + } 1.501 + 1.502 + public Void visitSignature(Signature_attribute attr, ClassOutputStream out) { 1.503 + out.writeShort(attr.signature_index); 1.504 + return null; 1.505 + } 1.506 + 1.507 + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, ClassOutputStream out) { 1.508 + out.write(attr.debug_extension, 0, attr.debug_extension.length); 1.509 + return null; 1.510 + } 1.511 + 1.512 + public Void visitSourceFile(SourceFile_attribute attr, ClassOutputStream out) { 1.513 + out.writeShort(attr.sourcefile_index); 1.514 + return null; 1.515 + } 1.516 + 1.517 + public Void visitSourceID(SourceID_attribute attr, ClassOutputStream out) { 1.518 + out.writeShort(attr.sourceID_index); 1.519 + return null; 1.520 + } 1.521 + 1.522 + public Void visitStackMap(StackMap_attribute attr, ClassOutputStream out) { 1.523 + if (stackMapWriter == null) 1.524 + stackMapWriter = new StackMapTableWriter(); 1.525 + 1.526 + out.writeShort(attr.entries.length); 1.527 + for (stack_map_frame f: attr.entries) 1.528 + stackMapWriter.write(f, out); 1.529 + return null; 1.530 + } 1.531 + 1.532 + public Void visitStackMapTable(StackMapTable_attribute attr, ClassOutputStream out) { 1.533 + if (stackMapWriter == null) 1.534 + stackMapWriter = new StackMapTableWriter(); 1.535 + 1.536 + out.writeShort(attr.entries.length); 1.537 + for (stack_map_frame f: attr.entries) 1.538 + stackMapWriter.write(f, out); 1.539 + return null; 1.540 + } 1.541 + 1.542 + public Void visitSynthetic(Synthetic_attribute attr, ClassOutputStream out) { 1.543 + return null; 1.544 + } 1.545 + 1.546 + protected void writeAccessFlags(AccessFlags flags, ClassOutputStream p) { 1.547 + sharedOut.writeShort(flags.flags); 1.548 + } 1.549 + 1.550 + protected StackMapTableWriter stackMapWriter; 1.551 + } 1.552 + 1.553 + /** 1.554 + * Writer for the frames of StackMap and StackMapTable attributes. 1.555 + */ 1.556 + protected static class StackMapTableWriter 1.557 + implements stack_map_frame.Visitor<Void,ClassOutputStream> { 1.558 + 1.559 + public void write(stack_map_frame frame, ClassOutputStream out) { 1.560 + out.write(frame.frame_type); 1.561 + frame.accept(this, out); 1.562 + } 1.563 + 1.564 + public Void visit_same_frame(same_frame frame, ClassOutputStream p) { 1.565 + return null; 1.566 + } 1.567 + 1.568 + public Void visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, ClassOutputStream out) { 1.569 + writeVerificationTypeInfo(frame.stack[0], out); 1.570 + return null; 1.571 + } 1.572 + 1.573 + public Void visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, ClassOutputStream out) { 1.574 + out.writeShort(frame.offset_delta); 1.575 + writeVerificationTypeInfo(frame.stack[0], out); 1.576 + return null; 1.577 + } 1.578 + 1.579 + public Void visit_chop_frame(chop_frame frame, ClassOutputStream out) { 1.580 + out.writeShort(frame.offset_delta); 1.581 + return null; 1.582 + } 1.583 + 1.584 + public Void visit_same_frame_extended(same_frame_extended frame, ClassOutputStream out) { 1.585 + out.writeShort(frame.offset_delta); 1.586 + return null; 1.587 + } 1.588 + 1.589 + public Void visit_append_frame(append_frame frame, ClassOutputStream out) { 1.590 + out.writeShort(frame.offset_delta); 1.591 + for (verification_type_info l: frame.locals) 1.592 + writeVerificationTypeInfo(l, out); 1.593 + return null; 1.594 + } 1.595 + 1.596 + public Void visit_full_frame(full_frame frame, ClassOutputStream out) { 1.597 + out.writeShort(frame.offset_delta); 1.598 + out.writeShort(frame.locals.length); 1.599 + for (verification_type_info l: frame.locals) 1.600 + writeVerificationTypeInfo(l, out); 1.601 + out.writeShort(frame.stack.length); 1.602 + for (verification_type_info s: frame.stack) 1.603 + writeVerificationTypeInfo(s, out); 1.604 + return null; 1.605 + } 1.606 + 1.607 + protected void writeVerificationTypeInfo(verification_type_info info, 1.608 + ClassOutputStream out) { 1.609 + out.write(info.tag); 1.610 + switch (info.tag) { 1.611 + case ITEM_Top: 1.612 + case ITEM_Integer: 1.613 + case ITEM_Float: 1.614 + case ITEM_Long: 1.615 + case ITEM_Double: 1.616 + case ITEM_Null: 1.617 + case ITEM_UninitializedThis: 1.618 + break; 1.619 + 1.620 + case ITEM_Object: 1.621 + Object_variable_info o = (Object_variable_info) info; 1.622 + out.writeShort(o.cpool_index); 1.623 + break; 1.624 + 1.625 + case ITEM_Uninitialized: 1.626 + Uninitialized_variable_info u = (Uninitialized_variable_info) info; 1.627 + out.writeShort(u.offset); 1.628 + break; 1.629 + 1.630 + default: 1.631 + throw new Error(); 1.632 + } 1.633 + } 1.634 + } 1.635 + 1.636 + /** 1.637 + * Writer for annotations and the values they contain. 1.638 + */ 1.639 + protected static class AnnotationWriter 1.640 + implements Annotation.element_value.Visitor<Void,ClassOutputStream> { 1.641 + public void write(Annotation[] annos, ClassOutputStream out) { 1.642 + out.writeShort(annos.length); 1.643 + for (Annotation anno: annos) 1.644 + write(anno, out); 1.645 + } 1.646 + 1.647 + public void write(Annotation anno, ClassOutputStream out) { 1.648 + out.writeShort(anno.type_index); 1.649 + out.writeShort(anno.element_value_pairs.length); 1.650 + for (element_value_pair p: anno.element_value_pairs) 1.651 + write(p, out); 1.652 + } 1.653 + 1.654 + public void write(element_value_pair pair, ClassOutputStream out) { 1.655 + out.writeShort(pair.element_name_index); 1.656 + write(pair.value, out); 1.657 + } 1.658 + 1.659 + public void write(element_value ev, ClassOutputStream out) { 1.660 + out.writeByte(ev.tag); 1.661 + ev.accept(this, out); 1.662 + } 1.663 + 1.664 + public Void visitPrimitive(Primitive_element_value ev, ClassOutputStream out) { 1.665 + out.writeShort(ev.const_value_index); 1.666 + return null; 1.667 + } 1.668 + 1.669 + public Void visitEnum(Enum_element_value ev, ClassOutputStream out) { 1.670 + out.writeShort(ev.type_name_index); 1.671 + out.writeShort(ev.const_name_index); 1.672 + return null; 1.673 + } 1.674 + 1.675 + public Void visitClass(Class_element_value ev, ClassOutputStream out) { 1.676 + out.writeShort(ev.class_info_index); 1.677 + return null; 1.678 + } 1.679 + 1.680 + public Void visitAnnotation(Annotation_element_value ev, ClassOutputStream out) { 1.681 + write(ev.annotation_value, out); 1.682 + return null; 1.683 + } 1.684 + 1.685 + public Void visitArray(Array_element_value ev, ClassOutputStream out) { 1.686 + out.writeShort(ev.num_values); 1.687 + for (element_value v: ev.values) 1.688 + write(v, out); 1.689 + return null; 1.690 + } 1.691 + } 1.692 +}