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