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 package com.sun.tools.javap;
27
28 import java.lang.classfile.Annotation;
29 import java.lang.classfile.Attribute;
30 import java.lang.classfile.Attributes;
31 import java.lang.classfile.Signature;
32 import java.lang.classfile.TypeAnnotation;
33 import java.lang.classfile.attribute.*;
34 import java.lang.classfile.constantpool.ModuleEntry;
35 import java.lang.classfile.constantpool.PoolEntry;
36 import java.lang.classfile.constantpool.Utf8Entry;
37 import java.lang.reflect.AccessFlag;
38 import java.lang.reflect.ClassFileFormatVersion;
39 import java.lang.reflect.Modifier;
40 import java.nio.charset.StandardCharsets;
41 import java.util.List;
42 import java.util.Locale;
43
44 import static java.lang.classfile.ClassFile.ACC_MANDATED;
45 import static java.lang.classfile.ClassFile.ACC_SYNTHETIC;
46 import static java.lang.classfile.attribute.StackMapFrameInfo.*;
47 import static java.lang.classfile.instruction.CharacterRange.*;
48
49 /*
50 * A writer for writing Attributes as text.
51 *
52 * <p><b>This is NOT part of any supported API.
53 * If you write code that depends on this, you do so at your own risk.
54 * This code and its internal interfaces are subject to change or
55 * deletion without notice.</b>
56 */
57 public class AttributeWriter extends BasicWriter {
58
59 public static AttributeWriter instance(Context context) {
60 AttributeWriter instance = context.get(AttributeWriter.class);
61 if (instance == null)
62 instance = new AttributeWriter(context);
63 return instance;
64 }
65
66 protected AttributeWriter(Context context) {
67 super(context);
68 context.put(AttributeWriter.class, this);
69 annotationWriter = AnnotationWriter.instance(context);
70 codeWriter = CodeWriter.instance(context);
71 constantWriter = ConstantWriter.instance(context);
72 options = Options.instance(context);
73 }
74
75 public void write(List<Attribute<?>> attrs, ClassFileFormatVersion cffv) {
76 write(attrs, null, cffv);
77 }
78
79 public void write(List<Attribute<?>> attrs, CodeAttribute lr, ClassFileFormatVersion cffv) {
80 if (attrs != null) {
81 for (var attr : attrs) try {
82 write(attr, lr, cffv);
83 } catch (IllegalArgumentException e) {
84 report(e);
85 }
86 }
87 }
88
201 var exc = attr.exceptions();
202 for (int i = 0; i < exc.size(); i++) {
203 if (i > 0)
204 print(", ");
205 print(getJavaName(exc.get(i).asInternalName()));
206 }
207 println();
208 indent(-1);
209 }
210 case InnerClassesAttribute attr -> {
211 boolean first = true;
212 for (var info : attr.classes()) {
213 //access
214 int access_flags = info.flagsMask();
215 if (options.checkAccess(access_flags)) {
216 if (first) {
217 println("InnerClasses:");
218 indent(+1);
219 first = false;
220 }
221 for (var flag : maskToAccessFlagsReportUnknown(access_flags, AccessFlag.Location.INNER_CLASS, cffv)) {
222 if (flag.sourceModifier() && (flag != AccessFlag.ABSTRACT
223 || !info.has(AccessFlag.INTERFACE))) {
224 print(Modifier.toString(flag.mask()) + " ");
225 }
226 }
227 if (info.innerName().isPresent()) {
228 print("#" + info.innerName().get().index() + "= ");
229 }
230 print("#" + info.innerClass().index());
231 if (info.outerClass().isPresent()) {
232 print(" of #" + info.outerClass().get().index());
233 }
234 print(";");
235 tab();
236 print("// ");
237 if (info.innerName().isPresent()) {
238 print(info.innerName().get().stringValue() + "=");
239 }
240 constantWriter.write(info.innerClass().index());
241 if (info.outerClass().isPresent()) {
242 print(" of ");
243 constantWriter.write(info.outerClass().get().index());
244 }
245 println();
246 }
247 }
248 if (!first)
249 indent(-1);
250 }
251 case LineNumberTableAttribute attr -> {
252 println("LineNumberTable:");
253 indent(+1);
254 for (var entry: attr.lineNumbers()) {
255 println("line " + entry.lineNumber() + ": " + entry.startPc());
256 }
257 indent(-1);
258 }
259 case LocalVariableTableAttribute attr -> {
260 println("LocalVariableTable:");
261 indent(+1);
262 println("Start Length Slot Name Signature");
263 for (var entry : attr.localVariables()) {
264 println(String.format("%5d %7d %5d %5s %s",
265 entry.startPc(), entry.length(), entry.slot(),
517 case RuntimeVisibleTypeAnnotationsAttribute attr ->
518 printTypeAnnotations("RuntimeVisibleTypeAnnotations:",
519 attr.annotations(), lr);
520 case RuntimeInvisibleTypeAnnotationsAttribute attr ->
521 printTypeAnnotations("RuntimeInvisibleTypeAnnotations:",
522 attr.annotations(), lr);
523 case RuntimeVisibleParameterAnnotationsAttribute attr ->
524 printParameterAnnotations("RuntimeVisibleParameterAnnotations:",
525 attr.parameterAnnotations());
526 case RuntimeInvisibleParameterAnnotationsAttribute attr ->
527 printParameterAnnotations("RuntimeInvisibleParameterAnnotations:",
528 attr.parameterAnnotations());
529 case PermittedSubclassesAttribute attr -> {
530 println("PermittedSubclasses:");
531 indent(+1);
532 for (var sc : attr.permittedSubclasses()) {
533 println(constantWriter.stringValue(sc));
534 }
535 indent(-1);
536 }
537 case SignatureAttribute attr -> {
538 print("Signature: #" + attr.signature().index());
539 tab();
540 println("// " + attr.signature().stringValue());
541 }
542 case SourceDebugExtensionAttribute attr -> {
543 println("SourceDebugExtension:");
544 indent(+1);
545 for (String s: new String(attr.contents(), StandardCharsets.UTF_8)
546 .split("[\r\n]+")) {
547 println(s);
548 }
549 indent(-1);
550 }
551 case SourceFileAttribute attr ->
552 println("SourceFile: \"" + attr.sourceFile().stringValue() + "\"");
553 case SourceIDAttribute attr ->
554 constantWriter.write(attr.sourceId().index());
555 case StackMapTableAttribute attr -> {
556 var entries = attr.entries();
557 println("StackMapTable: number_of_entries = " + entries.size());
558 indent(+1);
559 int lastOffset = -1;
560 for (var frame : entries) {
561 int frameType = frame.frameType();
562 if (frameType < 64) {
563 printHeader(frameType, "/* same */");
564 } else if (frameType < 128) {
565 printHeader(frameType, "/* same_locals_1_stack_item */");
566 indent(+1);
567 printMap("stack", frame.stack(), lr);
568 indent(-1);
569 } else {
570 int offsetDelta = lr.labelToBci(frame.target()) - lastOffset - 1;
571 switch (frameType) {
572 case 247 -> {
573 printHeader(frameType, "/* same_locals_1_stack_item_frame_extended */");
574 indent(+1);
575 println("offset_delta = " + offsetDelta);
576 printMap("stack", frame.stack(), lr);
577 indent(-1);
578 }
579 case 248, 249, 250 -> {
580 printHeader(frameType, "/* chop */");
581 indent(+1);
582 println("offset_delta = " + offsetDelta);
583 indent(-1);
584 }
585 case 251 -> {
586 printHeader(frameType, "/* same_frame_extended */");
587 indent(+1);
588 println("offset_delta = " + offsetDelta);
589 indent(-1);
590 }
591 case 252, 253, 254 -> {
592 printHeader(frameType, "/* append */");
593 indent(+1);
594 println("offset_delta = " + offsetDelta);
595 var locals = frame.locals();
596 printMap("locals", locals.subList(locals.size()
597 - frameType + 251, locals.size()), lr);
598 indent(-1);
599 }
600 case 255 -> {
601 printHeader(frameType, "/* full_frame */");
602 indent(+1);
603 println("offset_delta = " + offsetDelta);
604 printMap("locals", frame.locals(), lr);
605 printMap("stack", frame.stack(), lr);
606 indent(-1);
607 }
608 }
609 }
610 lastOffset = lr.labelToBci(frame.target());
611 }
612 indent(-1);
613 }
614 case SyntheticAttribute attr ->
615 println("Synthetic: true");
616 default -> {}
617 }
618 }
619
620 //ToDo move somewhere to Bytecode API
621 public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
735
736 static String toHex(int i) {
737 return Integer.toString(i, 16).toUpperCase(Locale.US);
738 }
739
740 static String toHex(int i, int w) {
741 String s = Integer.toHexString(i).toUpperCase(Locale.US);
742 while (s.length() < w)
743 s = "0" + s;
744 return s;
745 }
746
747 static String toHex(byte[] ba) {
748 StringBuilder sb = new StringBuilder(ba.length);
749 for (byte b: ba) {
750 sb.append(String.format("%02x", b & 0xff));
751 }
752 return sb.toString();
753 }
754
755 private final AnnotationWriter annotationWriter;
756 private final CodeWriter codeWriter;
757 private final ConstantWriter constantWriter;
758 private final Options options;
759 }
|
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 package com.sun.tools.javap;
27
28 import java.lang.classfile.Annotation;
29 import java.lang.classfile.Attribute;
30 import java.lang.classfile.Attributes;
31 import java.lang.classfile.Signature;
32 import java.lang.classfile.TypeAnnotation;
33 import java.lang.classfile.attribute.*;
34 import java.lang.classfile.constantpool.ModuleEntry;
35 import java.lang.classfile.constantpool.NameAndTypeEntry;
36 import java.lang.classfile.constantpool.PoolEntry;
37 import java.lang.classfile.constantpool.Utf8Entry;
38 import java.lang.reflect.AccessFlag;
39 import java.lang.reflect.ClassFileFormatVersion;
40 import java.lang.reflect.Modifier;
41 import java.nio.charset.StandardCharsets;
42 import java.util.List;
43 import java.util.Locale;
44
45 import static java.lang.classfile.ClassFile.ACC_MANDATED;
46 import static java.lang.classfile.ClassFile.ACC_SYNTHETIC;
47 import static java.lang.classfile.attribute.StackMapFrameInfo.*;
48 import static java.lang.classfile.instruction.CharacterRange.*;
49
50 import com.sun.tools.javac.util.Assert;
51 import com.sun.tools.javac.util.StringUtils;
52
53 /*
54 * A writer for writing Attributes as text.
55 *
56 * <p><b>This is NOT part of any supported API.
57 * If you write code that depends on this, you do so at your own risk.
58 * This code and its internal interfaces are subject to change or
59 * deletion without notice.</b>
60 */
61 public class AttributeWriter extends BasicWriter {
62
63 public static AttributeWriter instance(Context context) {
64 AttributeWriter instance = context.get(AttributeWriter.class);
65 if (instance == null)
66 instance = new AttributeWriter(context);
67 return instance;
68 }
69
70 protected AttributeWriter(Context context) {
71 super(context);
72 context.put(AttributeWriter.class, this);
73 classWriter = ClassWriter.instance(context);
74 annotationWriter = AnnotationWriter.instance(context);
75 codeWriter = CodeWriter.instance(context);
76 constantWriter = ConstantWriter.instance(context);
77 options = Options.instance(context);
78 }
79
80 public void write(List<Attribute<?>> attrs, ClassFileFormatVersion cffv) {
81 write(attrs, null, cffv);
82 }
83
84 public void write(List<Attribute<?>> attrs, CodeAttribute lr, ClassFileFormatVersion cffv) {
85 if (attrs != null) {
86 for (var attr : attrs) try {
87 write(attr, lr, cffv);
88 } catch (IllegalArgumentException e) {
89 report(e);
90 }
91 }
92 }
93
206 var exc = attr.exceptions();
207 for (int i = 0; i < exc.size(); i++) {
208 if (i > 0)
209 print(", ");
210 print(getJavaName(exc.get(i).asInternalName()));
211 }
212 println();
213 indent(-1);
214 }
215 case InnerClassesAttribute attr -> {
216 boolean first = true;
217 for (var info : attr.classes()) {
218 //access
219 int access_flags = info.flagsMask();
220 if (options.checkAccess(access_flags)) {
221 if (first) {
222 println("InnerClasses:");
223 indent(+1);
224 first = false;
225 }
226 var flagSet = maskToAccessFlagsReportUnknown(access_flags, AccessFlag.Location.INNER_CLASS, cffv);
227 for (var flag : flagSet) {
228 if (flag.sourceModifier() && (flag != AccessFlag.ABSTRACT
229 || !info.has(AccessFlag.INTERFACE))) {
230 print(Modifier.toString(flag.mask()) + " ");
231 }
232 }
233 if (info.innerName().isPresent()) {
234 print("#" + info.innerName().get().index() + "= ");
235 }
236 print("#" + info.innerClass().index());
237 if (info.outerClass().isPresent()) {
238 print(" of #" + info.outerClass().get().index());
239 }
240 print(";");
241 tab();
242 print("// ");
243 if (info.innerName().isPresent()) {
244 print(info.innerName().get().stringValue() + "=");
245 }
246 constantWriter.write(info.innerClass().index());
247 if (info.outerClass().isPresent()) {
248 print(" of ");
249 constantWriter.write(info.outerClass().get().index());
250 }
251 println();
252 if (options.verbose) {
253 indent(1);
254 classWriter.writeList(String.format("flags: (0x%04x) ", access_flags),
255 flagSet, "\n");
256 indent(-1);
257 }
258 }
259 }
260 if (!first)
261 indent(-1);
262 }
263 case LineNumberTableAttribute attr -> {
264 println("LineNumberTable:");
265 indent(+1);
266 for (var entry: attr.lineNumbers()) {
267 println("line " + entry.lineNumber() + ": " + entry.startPc());
268 }
269 indent(-1);
270 }
271 case LocalVariableTableAttribute attr -> {
272 println("LocalVariableTable:");
273 indent(+1);
274 println("Start Length Slot Name Signature");
275 for (var entry : attr.localVariables()) {
276 println(String.format("%5d %7d %5d %5s %s",
277 entry.startPc(), entry.length(), entry.slot(),
529 case RuntimeVisibleTypeAnnotationsAttribute attr ->
530 printTypeAnnotations("RuntimeVisibleTypeAnnotations:",
531 attr.annotations(), lr);
532 case RuntimeInvisibleTypeAnnotationsAttribute attr ->
533 printTypeAnnotations("RuntimeInvisibleTypeAnnotations:",
534 attr.annotations(), lr);
535 case RuntimeVisibleParameterAnnotationsAttribute attr ->
536 printParameterAnnotations("RuntimeVisibleParameterAnnotations:",
537 attr.parameterAnnotations());
538 case RuntimeInvisibleParameterAnnotationsAttribute attr ->
539 printParameterAnnotations("RuntimeInvisibleParameterAnnotations:",
540 attr.parameterAnnotations());
541 case PermittedSubclassesAttribute attr -> {
542 println("PermittedSubclasses:");
543 indent(+1);
544 for (var sc : attr.permittedSubclasses()) {
545 println(constantWriter.stringValue(sc));
546 }
547 indent(-1);
548 }
549 case LoadableDescriptorsAttribute attr -> {
550 println("LoadableDescriptors:");
551 indent(+1);
552 for (var sc : attr.loadableDescriptors()) {
553 println(constantWriter.stringValue(sc));
554 }
555 indent(-1);
556 }
557 case SignatureAttribute attr -> {
558 print("Signature: #" + attr.signature().index());
559 tab();
560 println("// " + attr.signature().stringValue());
561 }
562 case SourceDebugExtensionAttribute attr -> {
563 println("SourceDebugExtension:");
564 indent(+1);
565 for (String s: new String(attr.contents(), StandardCharsets.UTF_8)
566 .split("[\r\n]+")) {
567 println(s);
568 }
569 indent(-1);
570 }
571 case SourceFileAttribute attr ->
572 println("SourceFile: \"" + attr.sourceFile().stringValue() + "\"");
573 case SourceIDAttribute attr ->
574 constantWriter.write(attr.sourceId().index());
575 case StackMapTableAttribute attr -> {
576 var entries = attr.entries();
577 println("StackMapTable: number_of_entries = " + entries.size());
578 indent(+1);
579 int lastOffset = -1;
580 for (var frame : entries) {
581 int frameType = frame.frameType();
582 if (frameType < 64) {
583 printHeader(frameType, "/* same */");
584 } else if (frameType < 128) {
585 printHeader(frameType, "/* same_locals_1_stack_item */");
586 indent(+1);
587 printMap("stack", frame.stack(), lr);
588 indent(-1);
589 } else {
590 int offsetDelta = lr.labelToBci(frame.target()) - lastOffset - 1;
591 switch (frameType) {
592 case 246 -> {
593 printHeader(frameType, "/* early_larval */");
594 indent(+1);
595 println("number of unset_fields = " + frame.unsetFields().size());
596 indent(+1);
597 for (NameAndTypeEntry field : frame.unsetFields()) {
598 print("unset_field = #");
599 constantWriter.write(field.index());
600 println();
601 }
602 // temporary: print the nested contents of early larval
603 indent(+1);
604 println("offset_delta = " + offsetDelta);
605 printMap("locals", frame.locals(), lr);
606 printMap("stack", frame.stack(), lr);
607 indent(-1);
608 indent(-1);
609 indent(-1);
610 }
611 case 247 -> {
612 printHeader(frameType, "/* same_locals_1_stack_item_entry_extended */");
613 indent(+1);
614 println("offset_delta = " + offsetDelta);
615 printMap("stack", frame.stack(), lr);
616 indent(-1);
617 }
618 case 248, 249, 250 -> {
619 printHeader(frameType, "/* chop */");
620 indent(+1);
621 println("offset_delta = " + offsetDelta);
622 indent(-1);
623 }
624 case 251 -> {
625 printHeader(frameType, "/* same_entry_extended */");
626 indent(+1);
627 println("offset_delta = " + offsetDelta);
628 indent(-1);
629 }
630 case 252, 253, 254 -> {
631 printHeader(frameType, "/* append */");
632 indent(+1);
633 println("offset_delta = " + offsetDelta);
634 var locals = frame.locals();
635 printMap("locals", locals.subList(locals.size()
636 - frameType + 251, locals.size()), lr);
637 indent(-1);
638 }
639 case 255 -> {
640 printHeader(frameType, "/* full_entry */");
641 indent(+1);
642 println("offset_delta = " + offsetDelta);
643 printMap("locals", frame.locals(), lr);
644 printMap("stack", frame.stack(), lr);
645 indent(-1);
646 }
647 }
648 }
649 lastOffset = lr.labelToBci(frame.target());
650 }
651 indent(-1);
652 }
653 case SyntheticAttribute attr ->
654 println("Synthetic: true");
655 default -> {}
656 }
657 }
658
659 //ToDo move somewhere to Bytecode API
660 public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
774
775 static String toHex(int i) {
776 return Integer.toString(i, 16).toUpperCase(Locale.US);
777 }
778
779 static String toHex(int i, int w) {
780 String s = Integer.toHexString(i).toUpperCase(Locale.US);
781 while (s.length() < w)
782 s = "0" + s;
783 return s;
784 }
785
786 static String toHex(byte[] ba) {
787 StringBuilder sb = new StringBuilder(ba.length);
788 for (byte b: ba) {
789 sb.append(String.format("%02x", b & 0xff));
790 }
791 return sb.toString();
792 }
793
794 private final ClassWriter classWriter;
795 private final AnnotationWriter annotationWriter;
796 private final CodeWriter codeWriter;
797 private final ConstantWriter constantWriter;
798 private final Options options;
799 }
|