1 /*
2 * Copyright (c) 2007, 2024, 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 package com.sun.tools.javap;
27
28 import java.lang.reflect.Modifier;
29 import java.nio.charset.StandardCharsets;
30 import java.util.List;
31 import java.util.Locale;
32 import java.lang.classfile.*;
33 import java.lang.reflect.AccessFlag;
34 import java.lang.classfile.constantpool.*;
35 import java.lang.classfile.attribute.*;
36 import static java.lang.classfile.ClassFile.*;
37 import static java.lang.classfile.attribute.StackMapFrameInfo.*;
38 import static java.lang.classfile.instruction.CharacterRange.*;
39
40 /*
41 * A writer for writing Attributes as text.
42 *
43 * <p><b>This is NOT part of any supported API.
44 * If you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 public class AttributeWriter extends BasicWriter {
49
50 public static AttributeWriter instance(Context context) {
51 AttributeWriter instance = context.get(AttributeWriter.class);
52 if (instance == null)
53 instance = new AttributeWriter(context);
54 return instance;
55 }
56
57 protected AttributeWriter(Context context) {
58 super(context);
59 context.put(AttributeWriter.class, this);
508 case RuntimeVisibleTypeAnnotationsAttribute attr ->
509 printTypeAnnotations("RuntimeVisibleTypeAnnotations:",
510 attr.annotations(), lr);
511 case RuntimeInvisibleTypeAnnotationsAttribute attr ->
512 printTypeAnnotations("RuntimeInvisibleTypeAnnotations:",
513 attr.annotations(), lr);
514 case RuntimeVisibleParameterAnnotationsAttribute attr ->
515 printParameterAnnotations("RuntimeVisibleParameterAnnotations:",
516 attr.parameterAnnotations());
517 case RuntimeInvisibleParameterAnnotationsAttribute attr ->
518 printParameterAnnotations("RuntimeInvisibleParameterAnnotations:",
519 attr.parameterAnnotations());
520 case PermittedSubclassesAttribute attr -> {
521 println("PermittedSubclasses:");
522 indent(+1);
523 for (var sc : attr.permittedSubclasses()) {
524 println(constantWriter.stringValue(sc));
525 }
526 indent(-1);
527 }
528 case SignatureAttribute attr -> {
529 print("Signature: #" + attr.signature().index());
530 tab();
531 println("// " + attr.signature().stringValue());
532 }
533 case SourceDebugExtensionAttribute attr -> {
534 println("SourceDebugExtension:");
535 indent(+1);
536 for (String s: new String(attr.contents(), StandardCharsets.UTF_8)
537 .split("[\r\n]+")) {
538 println(s);
539 }
540 indent(-1);
541 }
542 case SourceFileAttribute attr ->
543 println("SourceFile: \"" + attr.sourceFile().stringValue() + "\"");
544 case SourceIDAttribute attr ->
545 constantWriter.write(attr.sourceId().index());
546 case StackMapTableAttribute attr -> {
547 var entries = attr.entries();
548 println("StackMapTable: number_of_entries = " + entries.size());
549 indent(+1);
550 int lastOffset = -1;
551 for (var frame : entries) {
552 int frameType = frame.frameType();
553 if (frameType < 64) {
554 printHeader(frameType, "/* same */");
555 } else if (frameType < 128) {
556 printHeader(frameType, "/* same_locals_1_stack_item */");
557 indent(+1);
558 printMap("stack", frame.stack(), lr);
559 indent(-1);
560 } else {
561 int offsetDelta = lr.labelToBci(frame.target()) - lastOffset - 1;
562 switch (frameType) {
563 case 247 -> {
564 printHeader(frameType, "/* same_locals_1_stack_item_frame_extended */");
565 indent(+1);
566 println("offset_delta = " + offsetDelta);
567 printMap("stack", frame.stack(), lr);
568 indent(-1);
569 }
570 case 248, 249, 250 -> {
571 printHeader(frameType, "/* chop */");
572 indent(+1);
573 println("offset_delta = " + offsetDelta);
574 indent(-1);
575 }
576 case 251 -> {
577 printHeader(frameType, "/* same_frame_extended */");
578 indent(+1);
579 println("offset_delta = " + offsetDelta);
580 indent(-1);
581 }
582 case 252, 253, 254 -> {
583 printHeader(frameType, "/* append */");
584 indent(+1);
585 println("offset_delta = " + offsetDelta);
586 var locals = frame.locals();
587 printMap("locals", locals.subList(locals.size()
588 - frameType + 251, locals.size()), lr);
589 indent(-1);
590 }
591 case 255 -> {
592 printHeader(frameType, "/* full_frame */");
593 indent(+1);
594 println("offset_delta = " + offsetDelta);
595 printMap("locals", frame.locals(), lr);
596 printMap("stack", frame.stack(), lr);
597 indent(-1);
598 }
599 }
600 }
601 lastOffset = lr.labelToBci(frame.target());
602 }
603 indent(-1);
604 }
605 case SyntheticAttribute attr ->
606 println("Synthetic: true");
607 default -> {}
608 }
609 }
610
611 //ToDo move somewhere to Bytecode API
612 public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
|
1 /*
2 * Copyright (c) 2007, 2025, 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 package com.sun.tools.javap;
27
28 import java.lang.reflect.Modifier;
29 import java.nio.charset.StandardCharsets;
30 import java.util.List;
31 import java.util.Locale;
32 import java.lang.classfile.*;
33 import java.lang.reflect.AccessFlag;
34 import java.lang.classfile.constantpool.*;
35 import java.lang.classfile.attribute.*;
36 import static java.lang.classfile.ClassFile.*;
37 import static java.lang.classfile.attribute.StackMapFrameInfo.*;
38 import static java.lang.classfile.instruction.CharacterRange.*;
39
40 import com.sun.tools.javac.util.Assert;
41 import com.sun.tools.javac.util.StringUtils;
42
43 /*
44 * A writer for writing Attributes as text.
45 *
46 * <p><b>This is NOT part of any supported API.
47 * If you write code that depends on this, you do so at your own risk.
48 * This code and its internal interfaces are subject to change or
49 * deletion without notice.</b>
50 */
51 public class AttributeWriter extends BasicWriter {
52
53 public static AttributeWriter instance(Context context) {
54 AttributeWriter instance = context.get(AttributeWriter.class);
55 if (instance == null)
56 instance = new AttributeWriter(context);
57 return instance;
58 }
59
60 protected AttributeWriter(Context context) {
61 super(context);
62 context.put(AttributeWriter.class, this);
511 case RuntimeVisibleTypeAnnotationsAttribute attr ->
512 printTypeAnnotations("RuntimeVisibleTypeAnnotations:",
513 attr.annotations(), lr);
514 case RuntimeInvisibleTypeAnnotationsAttribute attr ->
515 printTypeAnnotations("RuntimeInvisibleTypeAnnotations:",
516 attr.annotations(), lr);
517 case RuntimeVisibleParameterAnnotationsAttribute attr ->
518 printParameterAnnotations("RuntimeVisibleParameterAnnotations:",
519 attr.parameterAnnotations());
520 case RuntimeInvisibleParameterAnnotationsAttribute attr ->
521 printParameterAnnotations("RuntimeInvisibleParameterAnnotations:",
522 attr.parameterAnnotations());
523 case PermittedSubclassesAttribute attr -> {
524 println("PermittedSubclasses:");
525 indent(+1);
526 for (var sc : attr.permittedSubclasses()) {
527 println(constantWriter.stringValue(sc));
528 }
529 indent(-1);
530 }
531 case LoadableDescriptorsAttribute attr -> {
532 println("LoadableDescriptors:");
533 indent(+1);
534 for (var sc : attr.loadableDescriptors()) {
535 println(constantWriter.stringValue(sc));
536 }
537 indent(-1);
538 }
539 case SignatureAttribute attr -> {
540 print("Signature: #" + attr.signature().index());
541 tab();
542 println("// " + attr.signature().stringValue());
543 }
544 case SourceDebugExtensionAttribute attr -> {
545 println("SourceDebugExtension:");
546 indent(+1);
547 for (String s: new String(attr.contents(), StandardCharsets.UTF_8)
548 .split("[\r\n]+")) {
549 println(s);
550 }
551 indent(-1);
552 }
553 case SourceFileAttribute attr ->
554 println("SourceFile: \"" + attr.sourceFile().stringValue() + "\"");
555 case SourceIDAttribute attr ->
556 constantWriter.write(attr.sourceId().index());
557 case StackMapTableAttribute attr -> {
558 var entries = attr.entries();
559 println("StackMapTable: number_of_entries = " + entries.size());
560 indent(+1);
561 int lastOffset = -1;
562 for (var frame : entries) {
563 int frameType = frame.frameType();
564 if (frameType < 64) {
565 printHeader(frameType, "/* same */");
566 } else if (frameType < 128) {
567 printHeader(frameType, "/* same_locals_1_stack_item */");
568 indent(+1);
569 printMap("stack", frame.stack(), lr);
570 indent(-1);
571 } else {
572 int offsetDelta = frameType != 246 ? lr.labelToBci(frame.target()) - lastOffset - 1 : 0;
573 switch (frameType) {
574 case 246 -> {
575 printHeader(frameType, "/* assert_unset_fields */");
576 indent(+1);
577 println("number of unset_fields = " + frame.unsetFields().size());
578 indent(+1);
579 for (NameAndTypeEntry field : frame.unsetFields()) {
580 print("unset_field = #");
581 constantWriter.write(field.index());
582 println();
583 }
584 indent(-1);
585 indent(-1);
586 }
587 case 247 -> {
588 printHeader(frameType, "/* same_locals_1_stack_item_entry_extended */");
589 indent(+1);
590 println("offset_delta = " + offsetDelta);
591 printMap("stack", frame.stack(), lr);
592 indent(-1);
593 }
594 case 248, 249, 250 -> {
595 printHeader(frameType, "/* chop */");
596 indent(+1);
597 println("offset_delta = " + offsetDelta);
598 indent(-1);
599 }
600 case 251 -> {
601 printHeader(frameType, "/* same_entry_extended */");
602 indent(+1);
603 println("offset_delta = " + offsetDelta);
604 indent(-1);
605 }
606 case 252, 253, 254 -> {
607 printHeader(frameType, "/* append */");
608 indent(+1);
609 println("offset_delta = " + offsetDelta);
610 var locals = frame.locals();
611 printMap("locals", locals.subList(locals.size()
612 - frameType + 251, locals.size()), lr);
613 indent(-1);
614 }
615 case 255 -> {
616 printHeader(frameType, "/* full_entry */");
617 indent(+1);
618 println("offset_delta = " + offsetDelta);
619 printMap("locals", frame.locals(), lr);
620 printMap("stack", frame.stack(), lr);
621 indent(-1);
622 }
623 }
624 }
625 lastOffset = lr.labelToBci(frame.target());
626 }
627 indent(-1);
628 }
629 case SyntheticAttribute attr ->
630 println("Synthetic: true");
631 default -> {}
632 }
633 }
634
635 //ToDo move somewhere to Bytecode API
636 public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
|