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