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

Tue, 19 Feb 2013 17:19:01 -0800

author
ksrini
date
Tue, 19 Feb 2013 17:19:01 -0800
changeset 1592
9345394ac8fe
parent 1563
bc456436c613
child 1755
ddb4a2bfcd82
permissions
-rw-r--r--

8006948: Update javac for MethodParameters format change
Reviewed-by: ksrini, forax
Contributed-by: eric.mccorkle@oracle.com

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

mercurial