< prev index next >

src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java

Print this page

 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 }
< prev index next >