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

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

mercurial