diff --git a/src/java.base/share/classes/jdk/internal/classfile/ClassReader.java b/src/java.base/share/classes/jdk/internal/classfile/ClassReader.java index 7904038e41d..7884714dfde 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/ClassReader.java +++ b/src/java.base/share/classes/jdk/internal/classfile/ClassReader.java @@ -102,6 +102,16 @@ public sealed interface ClassReader extends ConstantPool */ PoolEntry readEntry(int offset); + /** + * {@return the constant pool entry of a given type whose index is given + * at the specified offset within the classfile} + * @param offset the offset of the index within the classfile + * @param cls the entry type + * @throws ConstantPoolException if the index is out of range of the + * constant pool size, or zero, or the entry is not of the given type + */ + T readEntry(int offset, Class cls); + /** * {@return the constant pool entry whose index is given at the specified * offset within the classfile, or null if the index at the specified diff --git a/src/java.base/share/classes/jdk/internal/classfile/constantpool/DynamicConstantPoolEntry.java b/src/java.base/share/classes/jdk/internal/classfile/constantpool/DynamicConstantPoolEntry.java index cd4ce92da0c..dda49a6e097 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/constantpool/DynamicConstantPoolEntry.java +++ b/src/java.base/share/classes/jdk/internal/classfile/constantpool/DynamicConstantPoolEntry.java @@ -38,6 +38,11 @@ public sealed interface DynamicConstantPoolEntry extends PoolEntry */ BootstrapMethodEntry bootstrap(); + /** + * {@return index of the entry in the bootstrap method table for this constant} + */ + int bootstrapMethodIndex(); + /** * {@return the invocation name and type} */ diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java index fa729ae961a..6d6a222d78d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java @@ -383,7 +383,7 @@ public abstract sealed class AbstractInstruction @Override public FieldRefEntry field() { if (fieldEntry == null) - fieldEntry = (FieldRefEntry) code.classReader.readEntry(pos + 1); + fieldEntry = code.classReader.readEntry(pos + 1, FieldRefEntry.class); return fieldEntry; } @@ -413,7 +413,7 @@ public abstract sealed class AbstractInstruction @Override public MemberRefEntry method() { if (methodEntry == null) - methodEntry = (MemberRefEntry) code.classReader.readEntry(pos + 1); + methodEntry = code.classReader.readEntry(pos + 1, MemberRefEntry.class); return methodEntry; } @@ -453,7 +453,7 @@ public abstract sealed class AbstractInstruction @Override public MemberRefEntry method() { if (methodEntry == null) - methodEntry = (InterfaceMethodRefEntry) code.classReader.readEntry(pos + 1); + methodEntry = code.classReader.readEntry(pos + 1, InterfaceMethodRefEntry.class); return methodEntry; } @@ -493,7 +493,7 @@ public abstract sealed class AbstractInstruction @Override public InvokeDynamicEntry invokedynamic() { if (indyEntry == null) - indyEntry = (InvokeDynamicEntry) code.classReader.readEntry(pos + 1); + indyEntry = code.classReader.readEntry(pos + 1, InvokeDynamicEntry.class); return indyEntry; } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java index 3b011920415..86a9bb10b58 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java @@ -815,6 +815,13 @@ public abstract sealed class AbstractPoolEntry { return bootstrapMethod; } + /** + * @return the bsmIndex + */ + public int bootstrapMethodIndex() { + return bsmIndex; + } + /** * @return the nameAndType */ diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java index ae80c1ced00..c4cfcaa119b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java @@ -58,14 +58,14 @@ class AnnotationReader { char tag = (char) classReader.readU1(p); ++p; return switch (tag) { - case AEV_BYTE -> new AnnotationImpl.OfByteImpl((IntegerEntry)classReader.readEntry(p)); - case AEV_CHAR -> new AnnotationImpl.OfCharacterImpl((IntegerEntry)classReader.readEntry(p)); - case AEV_DOUBLE -> new AnnotationImpl.OfDoubleImpl((DoubleEntry)classReader.readEntry(p)); - case AEV_FLOAT -> new AnnotationImpl.OfFloatImpl((FloatEntry)classReader.readEntry(p)); - case AEV_INT -> new AnnotationImpl.OfIntegerImpl((IntegerEntry)classReader.readEntry(p)); - case AEV_LONG -> new AnnotationImpl.OfLongImpl((LongEntry)classReader.readEntry(p)); - case AEV_SHORT -> new AnnotationImpl.OfShortImpl((IntegerEntry)classReader.readEntry(p)); - case AEV_BOOLEAN -> new AnnotationImpl.OfBooleanImpl((IntegerEntry)classReader.readEntry(p)); + case AEV_BYTE -> new AnnotationImpl.OfByteImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_CHAR -> new AnnotationImpl.OfCharacterImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_DOUBLE -> new AnnotationImpl.OfDoubleImpl(classReader.readEntry(p, DoubleEntry.class)); + case AEV_FLOAT -> new AnnotationImpl.OfFloatImpl(classReader.readEntry(p, FloatEntry.class)); + case AEV_INT -> new AnnotationImpl.OfIntegerImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_LONG -> new AnnotationImpl.OfLongImpl(classReader.readEntry(p, LongEntry.class)); + case AEV_SHORT -> new AnnotationImpl.OfShortImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_BOOLEAN -> new AnnotationImpl.OfBooleanImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_STRING -> new AnnotationImpl.OfStringImpl(classReader.readUtf8Entry(p)); case AEV_ENUM -> new AnnotationImpl.OfEnumImpl(classReader.readUtf8Entry(p), classReader.readUtf8Entry(p + 2)); case AEV_CLASS -> new AnnotationImpl.OfClassImpl(classReader.readUtf8Entry(p)); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java index 1a518b10f4d..179c170bf5e 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BoundAttribute.java @@ -483,7 +483,7 @@ public abstract sealed class BoundAttribute> @Override public ConstantValueEntry constant() { - return (ConstantValueEntry) classReader.readEntry(payloadStart); + return classReader.readEntry(payloadStart, ConstantValueEntry.class); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java index 70bd140f905..8e583012b94 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java @@ -27,7 +27,6 @@ package jdk.internal.classfile.impl; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.function.Function; @@ -37,10 +36,6 @@ import jdk.internal.classfile.attribute.BootstrapMethodsAttribute; import jdk.internal.classfile.constantpool.ClassEntry; import jdk.internal.classfile.constantpool.ConstantPoolException; import jdk.internal.classfile.constantpool.LoadableConstantEntry; -import jdk.internal.classfile.constantpool.MethodHandleEntry; -import jdk.internal.classfile.constantpool.ModuleEntry; -import jdk.internal.classfile.constantpool.NameAndTypeEntry; -import jdk.internal.classfile.constantpool.PackageEntry; import jdk.internal.classfile.constantpool.PoolEntry; import jdk.internal.classfile.constantpool.Utf8Entry; @@ -61,6 +56,10 @@ import static jdk.internal.classfile.Classfile.TAG_NAMEANDTYPE; import static jdk.internal.classfile.Classfile.TAG_PACKAGE; import static jdk.internal.classfile.Classfile.TAG_STRING; import static jdk.internal.classfile.Classfile.TAG_UTF8; +import jdk.internal.classfile.constantpool.MethodHandleEntry; +import jdk.internal.classfile.constantpool.ModuleEntry; +import jdk.internal.classfile.constantpool.NameAndTypeEntry; +import jdk.internal.classfile.constantpool.PackageEntry; public final class ClassReaderImpl implements ClassReader { @@ -156,7 +155,7 @@ public final class ClassReaderImpl @Override public ClassEntry thisClassEntry() { if (thisClass == null) { - thisClass = readClassEntry(thisClassPos); + thisClass = readEntry(thisClassPos, ClassEntry.class); } return thisClass; } @@ -391,6 +390,13 @@ public final class ClassReaderImpl return entryByIndex(readU2(pos)); } + @Override + public T readEntry(int pos, Class cls) { + var e = readEntry(pos); + if (cls.isInstance(e)) return cls.cast(e); + throw new ConstantPoolException("Not a " + cls.getSimpleName() + " at index: " + readU2(pos)); + } + @Override public PoolEntry readEntryOrNull(int pos) { int index = readU2(pos); @@ -417,32 +423,27 @@ public final class ClassReaderImpl @Override public ModuleEntry readModuleEntry(int pos) { - if (readEntry(pos) instanceof ModuleEntry me) return me; - throw new ConstantPoolException("Not a module entry at pos: " + pos); + return readEntry(pos, ModuleEntry.class); } @Override public PackageEntry readPackageEntry(int pos) { - if (readEntry(pos) instanceof PackageEntry pe) return pe; - throw new ConstantPoolException("Not a package entry at pos: " + pos); + return readEntry(pos, PackageEntry.class); } @Override public ClassEntry readClassEntry(int pos) { - if (readEntry(pos) instanceof ClassEntry ce) return ce; - throw new ConstantPoolException("Not a class entry at pos: " + pos); + return readEntry(pos, ClassEntry.class); } @Override public NameAndTypeEntry readNameAndTypeEntry(int pos) { - if (readEntry(pos) instanceof NameAndTypeEntry nate) return nate; - throw new ConstantPoolException("Not a name and type entry at pos: " + pos); + return readEntry(pos, NameAndTypeEntry.class); } @Override public MethodHandleEntry readMethodHandleEntry(int pos) { - if (readEntry(pos) instanceof MethodHandleEntry mhe) return mhe; - throw new ConstantPoolException("Not a method handle entry at pos: " + pos); + return readEntry(pos, MethodHandleEntry.class); } @Override diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index bf3d34abd7a..26be8e9b587 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -186,15 +186,19 @@ module java.base { java.logging; exports jdk.internal.classfile to jdk.jartool, + jdk.jdeps, jdk.jlink, jdk.jshell; exports jdk.internal.classfile.attribute to jdk.jartool, + jdk.jdeps, jdk.jlink; exports jdk.internal.classfile.constantpool to jdk.jartool, + jdk.jdeps, jdk.jlink; exports jdk.internal.classfile.instruction to + jdk.jdeps, jdk.jlink, jdk.jshell; exports jdk.internal.org.objectweb.asm to diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java index bfe3d231c4f..1501077ba62 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java @@ -25,17 +25,14 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Annotation; -import com.sun.tools.classfile.TypeAnnotation; -import com.sun.tools.classfile.Annotation.Annotation_element_value; -import com.sun.tools.classfile.Annotation.Array_element_value; -import com.sun.tools.classfile.Annotation.Class_element_value; -import com.sun.tools.classfile.Annotation.Enum_element_value; -import com.sun.tools.classfile.Annotation.Primitive_element_value; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import java.util.List; +import jdk.internal.classfile.Annotation; +import jdk.internal.classfile.AnnotationElement; +import jdk.internal.classfile.AnnotationValue; +import jdk.internal.classfile.constantpool.*; +import jdk.internal.classfile.Signature; +import jdk.internal.classfile.TypeAnnotation; +import jdk.internal.classfile.attribute.CodeAttribute; /** * A writer for writing annotations as text. @@ -68,15 +65,15 @@ public class AnnotationWriter extends BasicWriter { } public void write(Annotation annot, boolean resolveIndices) { - writeDescriptor(annot.type_index, resolveIndices); + writeDescriptor(annot.className(), resolveIndices); if (resolveIndices) { - boolean showParens = annot.num_element_value_pairs > 0; + boolean showParens = annot.elements().size() > 0; if (showParens) { println("("); indent(+1); } - for (int i = 0; i < annot.num_element_value_pairs; i++) { - write(annot.element_value_pairs[i], true); + for (var element : annot.elements()) { + write(element, true); println(); } if (showParens) { @@ -85,143 +82,126 @@ public class AnnotationWriter extends BasicWriter { } } else { print("("); - for (int i = 0; i < annot.num_element_value_pairs; i++) { + for (int i = 0; i < annot.elements().size(); i++) { if (i > 0) print(","); - write(annot.element_value_pairs[i], false); + write(annot.elements().get(i), false); } print(")"); } } - public void write(TypeAnnotation annot) { - write(annot, true, false); + public void write(TypeAnnotation annot, CodeAttribute lr) { + write(annot, true, false, lr); println(); indent(+1); - write(annot.annotation, true); + write(annot, true); indent(-1); } - public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) { - write(annot.annotation, resolveIndices); + public void write(TypeAnnotation annot, boolean showOffsets, + boolean resolveIndices, CodeAttribute lr) { + write(annot, resolveIndices); print(": "); - write(annot.position, showOffsets); + write(annot.targetInfo(), annot.targetPath(), showOffsets, lr); } - public void write(TypeAnnotation.Position pos, boolean showOffsets) { - print(pos.type); + public void write(TypeAnnotation.TargetInfo targetInfo, + List targetPath, + boolean showOffsets, CodeAttribute lr) { + print(targetInfo.targetType()); - switch (pos.type) { - // instanceof - case INSTANCEOF: - // new expression - case NEW: - // constructor/method reference receiver - case CONSTRUCTOR_REFERENCE: - case METHOD_REFERENCE: - if (showOffsets) { - print(", offset="); - print(pos.offset); - } - break; - // local variable - case LOCAL_VARIABLE: - // resource variable - case RESOURCE_VARIABLE: - if (pos.lvarOffset == null) { - print(", lvarOffset is Null!"); - break; - } - print(", {"); - for (int i = 0; i < pos.lvarOffset.length; ++i) { - if (i != 0) print("; "); + switch (targetInfo) { + // instanceof + // new expression + // constructor/method reference receiver + case TypeAnnotation.OffsetTarget pos -> { if (showOffsets) { - print("start_pc="); - print(pos.lvarOffset[i]); + print(", offset="); + print(lr.labelToBci(pos.target())); } - print(", length="); - print(pos.lvarLength[i]); - print(", index="); - print(pos.lvarIndex[i]); } - print("}"); - break; - // exception parameter - case EXCEPTION_PARAMETER: - print(", exception_index="); - print(pos.exception_index); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameter - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - print(", param_index="); - print(pos.parameter_index); - break; - // type parameter bound - case CLASS_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND: - print(", param_index="); - print(pos.parameter_index); - print(", bound_index="); - print(pos.bound_index); - break; - // class extends or implements clause - case CLASS_EXTENDS: - print(", type_index="); - print(pos.type_index); - break; - // throws - case THROWS: - print(", type_index="); - print(pos.type_index); - break; - // method parameter - case METHOD_FORMAL_PARAMETER: - print(", param_index="); - print(pos.parameter_index); - break; - // type cast - case CAST: - // method/constructor/reference type argument - case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: - case METHOD_INVOCATION_TYPE_ARGUMENT: - case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: - case METHOD_REFERENCE_TYPE_ARGUMENT: - if (showOffsets) { - print(", offset="); - print(pos.offset); + case TypeAnnotation.LocalVarTarget pos -> { + if (pos.table().isEmpty()) { + print(", lvarOffset is Null!"); + break; + } + print(", {"); + var table = pos.table(); + for (int i = 0; i < table.size(); ++i) { + var e = table.get(i); + if (i != 0) print("; "); + int startPc = lr.labelToBci(e.startLabel()); + if (showOffsets) { + print("start_pc="); + print(startPc); + } + print(", length="); + print(lr.labelToBci(e.endLabel()) - startPc); + print(", index="); + print(e.index()); + } + print("}"); } - print(", type_index="); - print(pos.type_index); - break; - // We don't need to worry about these - case METHOD_RETURN: - case FIELD: - break; - case UNKNOWN: - throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!"); - default: - throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos); + case TypeAnnotation.CatchTarget pos -> { + print(", exception_index="); + print(pos.exceptionTableIndex()); + } + case TypeAnnotation.TypeParameterTarget pos -> { + print(", param_index="); + print(pos.typeParameterIndex()); + } + case TypeAnnotation.TypeParameterBoundTarget pos -> { + print(", param_index="); + print(pos.typeParameterIndex()); + print(", bound_index="); + print(pos.boundIndex()); + } + case TypeAnnotation.SupertypeTarget pos -> { + print(", type_index="); + print(pos.supertypeIndex()); + } + case TypeAnnotation.ThrowsTarget pos -> { + print(", type_index="); + print(pos.throwsTargetIndex()); + } + case TypeAnnotation.FormalParameterTarget pos -> { + print(", param_index="); + print(pos.formalParameterIndex()); + } + case TypeAnnotation.TypeArgumentTarget pos -> { + if (showOffsets) { + print(", offset="); + print(lr.labelToBci(pos.target())); + } + print(", type_index="); + print(pos.typeArgumentIndex()); + } + case TypeAnnotation.EmptyTarget pos -> { + // Do nothing + } + default -> + throw new AssertionError("AnnotationWriter: Unhandled target type: " + + targetInfo.getClass()); } // Append location data for generics/arrays. - if (!pos.location.isEmpty()) { + if (!targetPath.isEmpty()) { print(", location="); - print(pos.location); + print(targetPath.stream().map(tp -> tp.typePathKind().toString() + + (tp.typePathKind() == TypeAnnotation.TypePathComponent.Kind.TYPE_ARGUMENT + ? ("(" + tp.typeArgumentIndex() + ")") + : "")).toList()); } } - public void write(Annotation.element_value_pair pair, boolean resolveIndices) { - writeIndex(pair.element_name_index, resolveIndices); + public void write(AnnotationElement pair, boolean resolveIndices) { + writeIndex(pair.name(), resolveIndices); print("="); - write(pair.value, resolveIndices); + write(pair.value(), resolveIndices); } - public void write(Annotation.element_value value) { + public void write(AnnotationValue value) { write(value, false); println(); indent(+1); @@ -229,122 +209,94 @@ public class AnnotationWriter extends BasicWriter { indent(-1); } - public void write(Annotation.element_value value, boolean resolveIndices) { - ev_writer.write(value, resolveIndices); - } - - private void writeDescriptor(int index, boolean resolveIndices) { + private void writeDescriptor(Utf8Entry entry, boolean resolveIndices) { if (resolveIndices) { - try { - ConstantPool constant_pool = classWriter.getClassFile().constant_pool; - Descriptor d = new Descriptor(index); - print(d.getFieldType(constant_pool)); - return; - } catch (ConstantPoolException | InvalidDescriptor ignore) { - } + print(classWriter.sigPrinter.print(Signature.parseFrom(entry.stringValue()))); + return; } - - print("#" + index); + print("#" + entry.index()); } - private void writeIndex(int index, boolean resolveIndices) { + private void writeIndex(PoolEntry entry, boolean resolveIndices) { if (resolveIndices) { - print(constantWriter.stringValue(index)); + print(constantWriter.stringValue(entry)); } else - print("#" + index); + print("#" + entry.index()); } - element_value_Writer ev_writer = new element_value_Writer(); - - class element_value_Writer implements Annotation.element_value.Visitor { - public void write(Annotation.element_value value, boolean resolveIndices) { - value.accept(this, resolveIndices); - } - - @Override - public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) { - if (resolveIndices) { - int index = ev.const_value_index; - switch (ev.tag) { - case 'B': - print("(byte) "); - print(constantWriter.stringValue(index)); - break; - case 'C': - print("'"); - print(constantWriter.charValue(index)); - print("'"); - break; - case 'D': - case 'F': - case 'I': - case 'J': - print(constantWriter.stringValue(index)); - break; - case 'S': - print("(short) "); - print(constantWriter.stringValue(index)); - break; - case 'Z': - print(constantWriter.booleanValue(index)); - break; - case 's': - print("\""); - print(constantWriter.stringValue(index)); - print("\""); - break; - default: - print(((char) ev.tag) + "#" + ev.const_value_index); - break; + public void write(AnnotationValue value, boolean resolveIndices) { + switch (value) { + case AnnotationValue.OfConstant ev -> { + if (resolveIndices) { + var entry = ev.constant(); + switch (ev.tag()) { + case 'B': + print("(byte) "); + print(constantWriter.stringValue(entry)); + break; + case 'C': + print("'"); + print(constantWriter.charValue(entry)); + print("'"); + break; + case 'D': + case 'F': + case 'I': + case 'J': + print(constantWriter.stringValue(entry)); + break; + case 'S': + print("(short) "); + print(constantWriter.stringValue(entry)); + break; + case 'Z': + print(constantWriter.booleanValue(entry)); + break; + case 's': + print("\""); + print(constantWriter.stringValue(entry)); + print("\""); + break; + default: + print(ev.tag() + "#" + entry.index()); + break; + } + } else { + print(ev.tag() + "#" + ev.constant().index()); } - } else { - print(((char) ev.tag) + "#" + ev.const_value_index); } - return null; - } - - @Override - public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) { - if (resolveIndices) { - writeIndex(ev.type_name_index, resolveIndices); - print("."); - writeIndex(ev.const_name_index, resolveIndices); - } else { - print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index); + case AnnotationValue.OfEnum ev -> { + if (resolveIndices) { + writeIndex(ev.className(), resolveIndices); + print("."); + writeIndex(ev.constantName(), resolveIndices); + } else { + print(ev.tag() + "#" + ev.className().index() + ".#" + + ev.constantName().index()); + } } - return null; - } - - @Override - public Void visitClass(Class_element_value ev, Boolean resolveIndices) { - if (resolveIndices) { - print("class "); - writeIndex(ev.class_info_index, resolveIndices); - } else { - print(((char) ev.tag) + "#" + ev.class_info_index); + case AnnotationValue.OfClass ev -> { + if (resolveIndices) { + print("class "); + writeIndex(ev.className(), resolveIndices); + } else { + print(ev.tag() + "#" + ev.className().index()); + } } - return null; - } - - @Override - public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) { - print((char) ev.tag); - AnnotationWriter.this.write(ev.annotation_value, resolveIndices); - return null; - } - - @Override - public Void visitArray(Array_element_value ev, Boolean resolveIndices) { - print("["); - for (int i = 0; i < ev.num_values; i++) { - if (i > 0) - print(","); - write(ev.values[i], resolveIndices); + case AnnotationValue.OfAnnotation ev -> { + print(ev.tag()); + AnnotationWriter.this.write(ev.annotation(), resolveIndices); + } + case AnnotationValue.OfArray ev -> { + print("["); + for (int i = 0; i < ev.values().size(); i++) { + if (i > 0) + print(","); + write(ev.values().get(i), resolveIndices); + } + print("]"); } - print("]"); - return null; } - } private final ClassWriter classWriter; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java index 67dbaebe827..13c5c10e890 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -25,63 +25,16 @@ package com.sun.tools.javap; -import java.util.Collection; - -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.AnnotationDefault_attribute; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Attributes; -import com.sun.tools.classfile.BootstrapMethods_attribute; -import com.sun.tools.classfile.CharacterRangeTable_attribute; -import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.CompilationID_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.ConstantValue_attribute; -import com.sun.tools.classfile.DefaultAttribute; -import com.sun.tools.classfile.Deprecated_attribute; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.EnclosingMethod_attribute; -import com.sun.tools.classfile.Exceptions_attribute; -import com.sun.tools.classfile.InnerClasses_attribute; -import com.sun.tools.classfile.InnerClasses_attribute.Info; -import com.sun.tools.classfile.LineNumberTable_attribute; -import com.sun.tools.classfile.LocalVariableTable_attribute; -import com.sun.tools.classfile.LocalVariableTypeTable_attribute; -import com.sun.tools.classfile.MethodParameters_attribute; -import com.sun.tools.classfile.Module_attribute; -import com.sun.tools.classfile.ModuleHashes_attribute; -import com.sun.tools.classfile.ModuleMainClass_attribute; -import com.sun.tools.classfile.ModulePackages_attribute; -import com.sun.tools.classfile.ModuleResolution_attribute; -import com.sun.tools.classfile.ModuleTarget_attribute; -import com.sun.tools.classfile.NestHost_attribute; -import com.sun.tools.classfile.NestMembers_attribute; -import com.sun.tools.classfile.Record_attribute; -import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.PermittedSubclasses_attribute; -import com.sun.tools.classfile.Signature_attribute; -import com.sun.tools.classfile.SourceDebugExtension_attribute; -import com.sun.tools.classfile.SourceFile_attribute; -import com.sun.tools.classfile.SourceID_attribute; -import com.sun.tools.classfile.StackMapTable_attribute; -import com.sun.tools.classfile.StackMap_attribute; -import com.sun.tools.classfile.Synthetic_attribute; -import com.sun.tools.classfile.Type; - -import static com.sun.tools.classfile.AccessFlags.*; - -import com.sun.tools.javac.util.Assert; -import com.sun.tools.javac.util.StringUtils; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Locale; +import jdk.internal.classfile.*; +import java.lang.reflect.AccessFlag; +import jdk.internal.classfile.constantpool.*; +import jdk.internal.classfile.attribute.*; +import static jdk.internal.classfile.Classfile.*; +import static jdk.internal.classfile.attribute.StackMapFrameInfo.*; /* * A writer for writing Attributes as text. @@ -91,9 +44,8 @@ import com.sun.tools.javac.util.StringUtils; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class AttributeWriter extends BasicWriter - implements Attribute.Visitor -{ +public class AttributeWriter extends BasicWriter { + public static AttributeWriter instance(Context context) { AttributeWriter instance = context.get(AttributeWriter.class); if (instance == null) @@ -110,446 +62,575 @@ public class AttributeWriter extends BasicWriter options = Options.instance(context); } - public void write(Object owner, Attribute attr, ConstantPool constant_pool) { - if (attr != null) { - Assert.checkNonNull(constant_pool); - Assert.checkNonNull(owner); - this.constant_pool = constant_pool; - this.owner = owner; - attr.accept(this, null); - } + public void write(List> attrs) { + write(attrs, null); } - public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { + public void write(List> attrs, CodeAttribute lr) { if (attrs != null) { - Assert.checkNonNull(constant_pool); - Assert.checkNonNull(owner); - this.constant_pool = constant_pool; - this.owner = owner; - for (Attribute attr: attrs) - attr.accept(this, null); + for (var attr : attrs) try { + write(attr, lr); + } catch (IllegalArgumentException e) { + report(e); + } } } - @Override - public Void visitDefault(DefaultAttribute attr, Void ignore) { - byte[] data = attr.info; - int i = 0; - int j = 0; - print(" "); - try { - print(attr.getName(constant_pool)); - } catch (ConstantPoolException e) { - report(e); - print("attribute name = #" + attr.attribute_name_index); - } - print(": "); - print("length = 0x" + toHex(attr.info.length)); - if (attr.reason != null) { - print(" (" + attr.reason + ")"); - } - println(); - - print(" "); - - while (i < data.length) { - print(toHex(data[i], 2)); - - j++; - if (j == 16) { + public void write(Attribute a, CodeAttribute lr) { + switch (a) { + case UnknownAttribute attr -> { + byte[] data = attr.contents(); + int i = 0; + int j = 0; + print(" "); + print(attr.attributeName()); + print(": "); + print("length = 0x" + toHex(data.length)); + print(" (unknown attribute)"); println(); print(" "); - j = 0; - } else { - print(" "); - } - i++; - } - println(); - return null; - } + while (i < data.length) { + print(toHex(data[i], 2)); - @Override - public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) { - println("AnnotationDefault:"); - indent(+1); - print("default_value: "); - annotationWriter.write(attr.default_value); - indent(-1); - println(); - return null; - } - - @Override - public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) { - println(Attribute.BootstrapMethods + ":"); - for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) { - BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i]; - indent(+1); - print(i + ": #" + bsm.bootstrap_method_ref + " "); - println(constantWriter.stringValue(bsm.bootstrap_method_ref)); - indent(+1); - println("Method arguments:"); - indent(+1); - for (int j = 0; j < bsm.bootstrap_arguments.length; j++) { - print("#" + bsm.bootstrap_arguments[j] + " "); - println(constantWriter.stringValue(bsm.bootstrap_arguments[j])); - } - indent(-3); - } - return null; - } - - @Override - public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) { - println("CharacterRangeTable:"); - indent(+1); - for (Entry e : attr.character_range_table) { - print(String.format(" %2d, %2d, %6x, %6x, %4x", - e.start_pc, e.end_pc, - e.character_range_start, e.character_range_end, - e.flags)); - tab(); - print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d", - e.start_pc, e.end_pc, - (e.character_range_start >> 10), (e.character_range_start & 0x3ff), - (e.character_range_end >> 10), (e.character_range_end & 0x3ff))); - if ((e.flags & CharacterRangeTable_attribute.CRT_STATEMENT) != 0) - print(", statement"); - if ((e.flags & CharacterRangeTable_attribute.CRT_BLOCK) != 0) - print(", block"); - if ((e.flags & CharacterRangeTable_attribute.CRT_ASSIGNMENT) != 0) - print(", assignment"); - if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_CONTROLLER) != 0) - print(", flow-controller"); - if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_TARGET) != 0) - print(", flow-target"); - if ((e.flags & CharacterRangeTable_attribute.CRT_INVOKE) != 0) - print(", invoke"); - if ((e.flags & CharacterRangeTable_attribute.CRT_CREATE) != 0) - print(", create"); - if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_TRUE) != 0) - print(", branch-true"); - if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_FALSE) != 0) - print(", branch-false"); - println(); - } - indent(-1); - return null; - } - - @Override - public Void visitCode(Code_attribute attr, Void ignore) { - codeWriter.write(attr, constant_pool); - return null; - } - - @Override - public Void visitCompilationID(CompilationID_attribute attr, Void ignore) { - constantWriter.write(attr.compilationID_index); - return null; - } - - @Override - public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) { - print("ConstantValue: "); - constantWriter.write(attr.constantvalue_index); - println(); - return null; - } - - @Override - public Void visitDeprecated(Deprecated_attribute attr, Void ignore) { - println("Deprecated: true"); - return null; - } - - @Override - public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) { - print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index); - tab(); - print("// " + getJavaClassName(attr)); - if (attr.method_index != 0) - print("." + getMethodName(attr)); - println(); - return null; - } - - private String getJavaClassName(EnclosingMethod_attribute a) { - try { - return getJavaName(a.getClassName(constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - private String getMethodName(EnclosingMethod_attribute a) { - try { - return a.getMethodName(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitExceptions(Exceptions_attribute attr, Void ignore) { - println("Exceptions:"); - indent(+1); - print("throws "); - for (int i = 0; i < attr.number_of_exceptions; i++) { - if (i > 0) - print(", "); - print(getJavaException(attr, i)); - } - println(); - indent(-1); - return null; - } - - private String getJavaException(Exceptions_attribute attr, int index) { - try { - return getJavaName(attr.getException(index, constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - - @Override - public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) { - boolean first = true; - for (Info info : attr.classes) { - //access - AccessFlags access_flags = info.inner_class_access_flags; - if (options.checkAccess(access_flags)) { - if (first) { - writeInnerClassHeader(); - first = false; - } - for (String name: access_flags.getInnerClassModifiers()) - print(name + " "); - if (info.inner_name_index != 0) { - print("#" + info.inner_name_index + "= "); - } - print("#" + info.inner_class_info_index); - if (info.outer_class_info_index != 0) { - print(" of #" + info.outer_class_info_index); - } - print(";"); - tab(); - print("// "); - if (info.inner_name_index != 0) { - print(getInnerName(constant_pool, info) + "="); - } - constantWriter.write(info.inner_class_info_index); - if (info.outer_class_info_index != 0) { - print(" of "); - constantWriter.write(info.outer_class_info_index); + j++; + if (j == 16) { + println(); + print(" "); + j = 0; + } else { + print(" "); + } + i++; } println(); } - } - if (!first) - indent(-1); - return null; - } + case AnnotationDefaultAttribute attr -> { + println("AnnotationDefault:"); + indent(+1); + print("default_value: "); + annotationWriter.write(attr.defaultValue()); + indent(-1); + println(); + } + case BootstrapMethodsAttribute attr -> { + println("BootstrapMethods:"); + for (int i = 0; i < attr.bootstrapMethodsSize() ; i++) { + var bsm = attr.bootstrapMethods().get(i); + indent(+1); + print(i + ": #" + bsm.bootstrapMethod().index() + " "); + println(constantWriter.stringValue(bsm.bootstrapMethod())); + indent(+1); + println("Method arguments:"); + indent(+1); + for (var arg : bsm.arguments()) { + print("#" + arg.index() + " "); + println(constantWriter.stringValue(arg)); + } + indent(-3); + } + } + case CharacterRangeTableAttribute attr -> { + println("CharacterRangeTable:"); + indent(+1); + for (var e : attr.characterRangeTable()) { + print(String.format(" %2d, %2d, %6x, %6x, %4x", + e.startPc(), e.endPc(), + e.characterRangeStart(), e.characterRangeEnd(), + e.flags())); + tab(); + print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d", + e.startPc(), e.endPc(), + (e.characterRangeStart() >> 10), + (e.characterRangeStart() & 0x3ff), + (e.characterRangeEnd() >> 10), + (e.characterRangeEnd() & 0x3ff))); + if ((e.flags() & CRT_STATEMENT) != 0) + print(", statement"); + if ((e.flags() & CRT_BLOCK) != 0) + print(", block"); + if ((e.flags() & CRT_ASSIGNMENT) != 0) + print(", assignment"); + if ((e.flags() & CRT_FLOW_CONTROLLER) != 0) + print(", flow-controller"); + if ((e.flags() & CRT_FLOW_TARGET) != 0) + print(", flow-target"); + if ((e.flags() & CRT_INVOKE) != 0) + print(", invoke"); + if ((e.flags() & CRT_CREATE) != 0) + print(", create"); + if ((e.flags() & CRT_BRANCH_TRUE) != 0) + print(", branch-true"); + if ((e.flags() & CRT_BRANCH_FALSE) != 0) + print(", branch-false"); + println(); + } + indent(-1); + } + case CodeAttribute attr -> codeWriter.write(attr); + case CompilationIDAttribute attr -> + constantWriter.write(attr.compilationId().index()); + case ConstantValueAttribute attr -> { + print("ConstantValue: "); + constantWriter.write(attr.constant().index()); + println(); + } + case DeprecatedAttribute attr -> println("Deprecated: true"); + case EnclosingMethodAttribute attr -> { + print("EnclosingMethod: #" + attr.enclosingClass().index() + ".#" + + attr.enclosingMethod().map(PoolEntry::index).orElse(0)); + tab(); + print("// " + getJavaName(attr.enclosingClass().asInternalName())); + if (attr.enclosingMethod().isPresent()) + print("." + attr.enclosingMethod().get().name().stringValue()); + println(); + } + case ExceptionsAttribute attr -> { + println("Exceptions:"); + indent(+1); + print("throws "); + var exc = attr.exceptions(); + for (int i = 0; i < exc.size(); i++) { + if (i > 0) + print(", "); + print(getJavaName(exc.get(i).asInternalName())); + } + println(); + indent(-1); + } + case InnerClassesAttribute attr -> { + boolean first = true; + for (var info : attr.classes()) { + //access + int access_flags = info.flagsMask(); + if (options.checkAccess(access_flags)) { + if (first) { + println("InnerClasses:"); + indent(+1); + first = false; + } + for (var flag : info.flags()) { + if (flag.sourceModifier() && (flag != AccessFlag.ABSTRACT + || !info.has(AccessFlag.INTERFACE))) { + print(Modifier.toString(flag.mask()) + " "); + } + } + if (info.innerName().isPresent()) { + print("#" + info.innerName().get().index() + "= "); + } + print("#" + info.innerClass().index()); + if (info.outerClass().isPresent()) { + print(" of #" + info.outerClass().get().index()); + } + print(";"); + tab(); + print("// "); + if (info.innerName().isPresent()) { + print(info.innerName().get().stringValue() + "="); + } + constantWriter.write(info.innerClass().index()); + if (info.outerClass().isPresent()) { + print(" of "); + constantWriter.write(info.outerClass().get().index()); + } + println(); + } + } + if (!first) + indent(-1); + } + case LineNumberTableAttribute attr -> { + println("LineNumberTable:"); + indent(+1); + for (var entry: attr.lineNumbers()) { + println("line " + entry.lineNumber() + ": " + entry.startPc()); + } + indent(-1); + } + case LocalVariableTableAttribute attr -> { + println("LocalVariableTable:"); + indent(+1); + println("Start Length Slot Name Signature"); + for (var entry : attr.localVariables()) { + println(String.format("%5d %7d %5d %5s %s", + entry.startPc(), entry.length(), entry.slot(), + constantWriter.stringValue(entry.name()), + constantWriter.stringValue(entry.type()))); + } + indent(-1); + } + case LocalVariableTypeTableAttribute attr -> { + println("LocalVariableTypeTable:"); + indent(+1); + println("Start Length Slot Name Signature"); + for (var entry : attr.localVariableTypes()) { + println(String.format("%5d %7d %5d %5s %s", + entry.startPc(), entry.length(), entry.slot(), + constantWriter.stringValue(entry.name()), + constantWriter.stringValue(entry.signature()))); + } + indent(-1); + } + case NestHostAttribute attr -> { + print("NestHost: "); + constantWriter.write(attr.nestHost().index()); + println(); + } + case MethodParametersAttribute attr -> { + final String header = String.format(format, "Name", "Flags"); + println("MethodParameters:"); + indent(+1); + println(header); + for (var entry : attr.parameters()) { + String namestr = + entry.name().isPresent() ? + constantWriter.stringValue(entry.name().get()) : ""; + String flagstr = + (entry.has(AccessFlag.FINAL) ? "final " : "") + + (entry.has(AccessFlag.MANDATED) ? "mandated " : "") + + (entry.has(AccessFlag.SYNTHETIC) ? "synthetic" : ""); + println(String.format(format, namestr, flagstr)); + } + indent(-1); + } + case ModuleAttribute attr -> { + println("Module:"); + indent(+1); - String getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info) { - try { - return info.getInnerName(constant_pool); - } catch (ConstantPoolException e) { - return report(e); + print("#" + attr.moduleName().index()); + print(","); + print(String.format("%x", attr.moduleFlagsMask())); + tab(); + print("// " + constantWriter.stringValue(attr.moduleName())); + if (attr.has(AccessFlag.OPEN)) + print(" ACC_OPEN"); + if (attr.has(AccessFlag.MANDATED)) + print(" ACC_MANDATED"); + if (attr.has(AccessFlag.SYNTHETIC)) + print(" ACC_SYNTHETIC"); + println(); + var ver = attr.moduleVersion(); + print("#" + ver.map(Utf8Entry::index).orElse(0)); + if (ver.isPresent()) { + tab(); + print("// " + constantWriter.stringValue(ver.get())); + } + println(); + { + var entries = attr.requires(); + print(entries.size()); + tab(); + println("// " + "requires"); + indent(+1); + for (var e: entries) { + print("#" + e.requires().index() + "," + + String.format("%x", e.requiresFlagsMask())); + tab(); + print("// " + constantWriter.stringValue(e.requires())); + if (e.has(AccessFlag.TRANSITIVE)) + print(" ACC_TRANSITIVE"); + if (e.has(AccessFlag.STATIC_PHASE)) + print(" ACC_STATIC_PHASE"); + if (e.has(AccessFlag.SYNTHETIC)) + print(" ACC_SYNTHETIC"); + if (e.has(AccessFlag.MANDATED)) + print(" ACC_MANDATED"); + println(); + var reqVer = e.requiresVersion(); + print("#" + reqVer.map(Utf8Entry::index).orElse(0)); + if (reqVer.isPresent()) { + tab(); + print("// " + constantWriter.stringValue(reqVer.get())); + } + println(); + } + indent(-1); + } + { + var entries = attr.exports(); + print(entries.size()); + tab(); + println("// exports"); + indent(+1); + for (var e: entries) { + printExportOpenEntry(e.exportedPackage().index(), + e.exportsFlagsMask(), e.exportsTo()); + } + indent(-1); + } + { + var entries = attr.opens(); + print(entries.size()); + tab(); + println("// opens"); + indent(+1); + for (var e: entries) { + printExportOpenEntry(e.openedPackage().index(), + e.opensFlagsMask(), e.opensTo()); + } + indent(-1); + } + { + var entries = attr.uses(); + print(entries.size()); + tab(); + println("// " + "uses"); + indent(+1); + for (var e: entries) { + print("#" + e.index()); + tab(); + println("// " + constantWriter.stringValue(e)); + } + indent(-1); + } + { + var entries = attr.provides(); + print(entries.size()); + tab(); + println("// " + "provides"); + indent(+1); + for (var e: entries) { + print("#" + e.provides().index()); + tab(); + print("// "); + print(constantWriter.stringValue(e.provides())); + println(" with ... " + e.providesWith().size()); + indent(+1); + for (var with : e.providesWith()) { + print("#" + with.index()); + tab(); + println("// ... with " + constantWriter.stringValue(with)); + } + indent(-1); + } + indent(-1); + } + indent(-1); + } + case ModuleHashesAttribute attr -> { + println("ModuleHashes:"); + indent(+1); + print("algorithm: #" + attr.algorithm().index()); + tab(); + println("// " + attr.algorithm().stringValue()); + print(attr.hashes().size()); + tab(); + println("// hashes"); + for (var e : attr.hashes()) { + print("#" + e.moduleName().index()); + tab(); + println("// " + e.moduleName().name().stringValue()); + println("hash_length: " + e.hash().length); + println("hash: [" + toHex(e.hash()) + "]"); + } + indent(-1); + } + case ModuleMainClassAttribute attr -> { + print("ModuleMainClass: #" + attr.mainClass().index()); + tab(); + print("// " + getJavaName(attr.mainClass().asInternalName())); + println(); + } + case ModulePackagesAttribute attr -> { + println("ModulePackages: "); + indent(+1); + for (var p : attr.packages()) { + print("#" + p.index()); + tab(); + println("// " + getJavaName(p.name().stringValue())); + } + indent(-1); + } + case ModuleResolutionAttribute attr -> { + println("ModuleResolution:"); + indent(+1); + print(String.format("%x", attr.resolutionFlags())); + tab(); + print("// "); + int flags = attr.resolutionFlags(); + if ((flags & DO_NOT_RESOLVE_BY_DEFAULT) != 0) + print(" DO_NOT_RESOLVE_BY_DEFAULT"); + if ((flags & WARN_DEPRECATED) != 0) + print(" WARN_DEPRECATED"); + if ((flags & WARN_DEPRECATED_FOR_REMOVAL) != 0) + print(" WARN_DEPRECATED_FOR_REMOVAL"); + if ((flags & WARN_INCUBATING) != 0) + print(" WARN_INCUBATING"); + println(); + indent(-1); + } + case ModuleTargetAttribute attr -> { + println("ModuleTarget:"); + indent(+1); + print("target_platform: #" + attr.targetPlatform().index()); + tab(); + println("// " + attr.targetPlatform().stringValue()); + indent(-1); + } + case NestMembersAttribute attr -> { + println("NestMembers:"); + indent(+1); + for (var m : attr.nestMembers()) { + println(constantWriter.stringValue(m)); + } + indent(-1); + } + case RecordAttribute attr -> { + println("Record:"); + indent(+1); + for (var componentInfo : attr.components()) { + var sigAttr = componentInfo.findAttribute(Attributes.SIGNATURE); + print(getJavaName( + new ClassWriter.SignaturePrinter(options.verbose).print( + sigAttr.map(SignatureAttribute::asTypeSignature) + .orElse(Signature.of( + componentInfo.descriptorSymbol()))))); + print(" "); + print(componentInfo.name().stringValue()); + print(";"); + println(); + indent(+1); + if (options.showDescriptors) { + println("descriptor: " + componentInfo.descriptor().stringValue()); + } + if (options.showAllAttrs) { + write(componentInfo.attributes()); + println(); + } + indent(-1); + } + indent(-1); + } + case RuntimeVisibleAnnotationsAttribute attr -> + printAnnotations("RuntimeVisibleAnnotations:", attr.annotations()); + case RuntimeInvisibleAnnotationsAttribute attr -> + printAnnotations("RuntimeInvisibleAnnotations:", attr.annotations()); + case RuntimeVisibleTypeAnnotationsAttribute attr -> + printTypeAnnotations("RuntimeVisibleTypeAnnotations:", + attr.annotations(), lr); + case RuntimeInvisibleTypeAnnotationsAttribute attr -> + printTypeAnnotations("RuntimeInvisibleTypeAnnotations:", + attr.annotations(), lr); + case RuntimeVisibleParameterAnnotationsAttribute attr -> + printParameterAnnotations("RuntimeVisibleParameterAnnotations:", + attr.parameterAnnotations()); + case RuntimeInvisibleParameterAnnotationsAttribute attr -> + printParameterAnnotations("RuntimeInvisibleParameterAnnotations:", + attr.parameterAnnotations()); + case PermittedSubclassesAttribute attr -> { + println("PermittedSubclasses:"); + indent(+1); + for (var sc : attr.permittedSubclasses()) { + println(constantWriter.stringValue(sc)); + } + indent(-1); + } + case SignatureAttribute attr -> { + print("Signature: #" + attr.signature().index()); + tab(); + println("// " + attr.signature().stringValue()); + } + case SourceDebugExtensionAttribute attr -> { + println("SourceDebugExtension:"); + indent(+1); + for (String s: new String(attr.contents(), StandardCharsets.UTF_8) + .split("[\r\n]+")) { + println(s); + } + indent(-1); + } + case SourceFileAttribute attr -> + println("SourceFile: \"" + attr.sourceFile().stringValue() + "\""); + case SourceIDAttribute attr -> + constantWriter.write(attr.sourceId().index()); + case StackMapTableAttribute attr -> { + var entries = attr.entries(); + println("StackMapTable: number_of_entries = " + entries.size()); + indent(+1); + int lastOffset = -1; + for (var frame : entries) { + int frameType = frame.frameType(); + if (frameType < 64) { + printHeader(frameType, "/* same */"); + } else if (frameType < 128) { + printHeader(frameType, "/* same_locals_1_stack_item */"); + indent(+1); + printMap("stack", frame.stack(), lr); + indent(-1); + } else { + int offsetDelta = lr.labelToBci(frame.target()) - lastOffset - 1; + switch (frameType) { + case 247 -> { + printHeader(frameType, "/* same_locals_1_stack_item_frame_extended */"); + indent(+1); + println("offset_delta = " + offsetDelta); + printMap("stack", frame.stack(), lr); + indent(-1); + } + case 248, 249, 250 -> { + printHeader(frameType, "/* chop */"); + indent(+1); + println("offset_delta = " + offsetDelta); + indent(-1); + } + case 251 -> { + printHeader(frameType, "/* same_frame_extended */"); + indent(+1); + println("offset_delta = " + offsetDelta); + indent(-1); + } + case 252, 253, 254 -> { + printHeader(frameType, "/* append */"); + indent(+1); + println("offset_delta = " + offsetDelta); + var locals = frame.locals(); + printMap("locals", locals.subList(locals.size() + - frameType + 251, locals.size()), lr); + indent(-1); + } + case 255 -> { + printHeader(frameType, "/* full_frame */"); + indent(+1); + println("offset_delta = " + offsetDelta); + printMap("locals", frame.locals(), lr); + printMap("stack", frame.stack(), lr); + indent(-1); + } + } + } + lastOffset = lr.labelToBci(frame.target()); + } + indent(-1); + } + case SyntheticAttribute attr -> + println("Synthetic: true"); + default -> {} } } - private void writeInnerClassHeader() { - println("InnerClasses:"); - indent(+1); - } - - @Override - public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) { - println("LineNumberTable:"); - indent(+1); - for (LineNumberTable_attribute.Entry entry: attr.line_number_table) { - println("line " + entry.line_number + ": " + entry.start_pc); - } - indent(-1); - return null; - } - - @Override - public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) { - println("LocalVariableTable:"); - indent(+1); - println("Start Length Slot Name Signature"); - for (LocalVariableTable_attribute.Entry entry : attr.local_variable_table) { - println(String.format("%5d %7d %5d %5s %s", - entry.start_pc, entry.length, entry.index, - constantWriter.stringValue(entry.name_index), - constantWriter.stringValue(entry.descriptor_index))); - } - indent(-1); - return null; - } - - @Override - public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) { - println("LocalVariableTypeTable:"); - indent(+1); - println("Start Length Slot Name Signature"); - for (LocalVariableTypeTable_attribute.Entry entry : attr.local_variable_table) { - println(String.format("%5d %7d %5d %5s %s", - entry.start_pc, entry.length, entry.index, - constantWriter.stringValue(entry.name_index), - constantWriter.stringValue(entry.signature_index))); - } - indent(-1); - return null; - } - - @Override - public Void visitNestHost(NestHost_attribute attr, Void aVoid) { - print("NestHost: "); - constantWriter.write(attr.top_index); - println(); - return null; - } - - private String getJavaClassName(ModuleMainClass_attribute a) { - try { - return getJavaName(a.getMainClassName(constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } - } + //ToDo move somewhere to Bytecode API + public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001; + public static final int WARN_DEPRECATED = 0x0002; + public static final int WARN_DEPRECATED_FOR_REMOVAL = 0x0004; + public static final int WARN_INCUBATING = 0x0008; private static final String format = "%-31s%s"; - @Override - public Void visitMethodParameters(MethodParameters_attribute attr, - Void ignore) { - final String header = String.format(format, "Name", "Flags"); - println("MethodParameters:"); - indent(+1); - println(header); - for (MethodParameters_attribute.Entry entry : - attr.method_parameter_table) { - String namestr = - entry.name_index != 0 ? - constantWriter.stringValue(entry.name_index) : ""; - String flagstr = - (0 != (entry.flags & ACC_FINAL) ? "final " : "") + - (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") + - (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : ""); - println(String.format(format, namestr, flagstr)); - } - indent(-1); - return null; - } - - @Override - public Void visitModule(Module_attribute attr, Void ignore) { - println("Module:"); - indent(+1); - - print("#" + attr.module_name); - print(","); - print(String.format("%x", attr.module_flags)); - tab(); - print("// " + constantWriter.stringValue(attr.module_name)); - if ((attr.module_flags & Module_attribute.ACC_OPEN) != 0) - print(" ACC_OPEN"); - if ((attr.module_flags & Module_attribute.ACC_MANDATED) != 0) - print(" ACC_MANDATED"); - if ((attr.module_flags & Module_attribute.ACC_SYNTHETIC) != 0) - print(" ACC_SYNTHETIC"); - println(); - print("#" + attr.module_version_index); - if (attr.module_version_index != 0) { - tab(); - print("// " + constantWriter.stringValue(attr.module_version_index)); - } - println(); - - printRequiresTable(attr); - printExportsTable(attr); - printOpensTable(attr); - printUsesTable(attr); - printProvidesTable(attr); - indent(-1); - return null; - } - - protected void printRequiresTable(Module_attribute attr) { - Module_attribute.RequiresEntry[] entries = attr.requires; - print(entries.length); - tab(); - println("// " + "requires"); - indent(+1); - for (Module_attribute.RequiresEntry e: entries) { - print("#" + e.requires_index + "," + String.format("%x", e.requires_flags)); - tab(); - print("// " + constantWriter.stringValue(e.requires_index)); - if ((e.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0) - print(" ACC_TRANSITIVE"); - if ((e.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0) - print(" ACC_STATIC_PHASE"); - if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0) - print(" ACC_SYNTHETIC"); - if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0) - print(" ACC_MANDATED"); - println(); - print("#" + e.requires_version_index); - if (e.requires_version_index != 0) { - tab(); - print("// " + constantWriter.stringValue(e.requires_version_index)); - } - println(); - } - indent(-1); - } - - protected void printExportsTable(Module_attribute attr) { - Module_attribute.ExportsEntry[] entries = attr.exports; - print(entries.length); - tab(); - println("// exports"); - indent(+1); - for (Module_attribute.ExportsEntry e: entries) { - printExportOpenEntry(e.exports_index, e.exports_flags, e.exports_to_index); - } - indent(-1); - } - - protected void printOpensTable(Module_attribute attr) { - Module_attribute.OpensEntry[] entries = attr.opens; - print(entries.length); - tab(); - println("// opens"); - indent(+1); - for (Module_attribute.OpensEntry e: entries) { - printExportOpenEntry(e.opens_index, e.opens_flags, e.opens_to_index); - } - indent(-1); - } - - protected void printExportOpenEntry(int index, int flags, int[] to_index) { + protected void printExportOpenEntry(int index, int flags, List to_index) { print("#" + index + "," + String.format("%x", flags)); tab(); print("// "); print(constantWriter.stringValue(index)); - if ((flags & Module_attribute.ACC_MANDATED) != 0) + if ((flags & ACC_MANDATED) != 0) print(" ACC_MANDATED"); - if ((flags & Module_attribute.ACC_SYNTHETIC) != 0) + if ((flags & ACC_SYNTHETIC) != 0) print(" ACC_SYNTHETIC"); - if (to_index.length == 0) { + if (to_index.size() == 0) { println(); } else { - println(" to ... " + to_index.length); + println(" to ... " + to_index.size()); indent(+1); - for (int to: to_index) { - print("#" + to); + for (var to: to_index) { + print("#" + to.index()); tab(); println("// ... to " + constantWriter.stringValue(to)); } @@ -557,311 +638,39 @@ public class AttributeWriter extends BasicWriter } } - protected void printUsesTable(Module_attribute attr) { - int[] entries = attr.uses_index; - print(entries.length); - tab(); - println("// " + "uses"); - indent(+1); - for (int e: entries) { - print("#" + e); - tab(); - println("// " + constantWriter.stringValue(e)); - } - indent(-1); - } - - protected void printProvidesTable(Module_attribute attr) { - Module_attribute.ProvidesEntry[] entries = attr.provides; - print(entries.length); - tab(); - println("// " + "provides"); - indent(+1); - for (Module_attribute.ProvidesEntry e: entries) { - print("#" + e.provides_index); - tab(); - print("// "); - print(constantWriter.stringValue(e.provides_index)); - println(" with ... " + e.with_count); - indent(+1); - for (int with : e.with_index) { - print("#" + with); - tab(); - println("// ... with " + constantWriter.stringValue(with)); - } - indent(-1); - } - indent(-1); - } - - @Override - public Void visitModuleHashes(ModuleHashes_attribute attr, Void ignore) { - println("ModuleHashes:"); - indent(+1); - print("algorithm: #" + attr.algorithm_index); - tab(); - println("// " + getAlgorithm(attr)); - print(attr.hashes_table_length); - tab(); - println("// hashes"); - for (ModuleHashes_attribute.Entry e : attr.hashes_table) { - print("#" + e.module_name_index); - tab(); - println("// " + getModuleName(e)); - println("hash_length: " + e.hash.length); - println("hash: [" + toHex(e.hash) + "]"); - } - indent(-1); - return null; - } - - private String getAlgorithm(ModuleHashes_attribute attr) { - try { - return constant_pool.getUTF8Value(attr.algorithm_index); - } catch (ConstantPoolException e) { - return report(e); - } - } - - private String getModuleName(ModuleHashes_attribute.Entry entry) { - try { - int utf8Index = constant_pool.getModuleInfo(entry.module_name_index).name_index; - return constant_pool.getUTF8Value(utf8Index); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitModuleMainClass(ModuleMainClass_attribute attr, Void ignore) { - print("ModuleMainClass: #" + attr.main_class_index); - tab(); - print("// " + getJavaClassName(attr)); - println(); - return null; - } - - @Override - public Void visitModulePackages(ModulePackages_attribute attr, Void ignore) { - println("ModulePackages: "); - indent(+1); - for (int i = 0; i < attr.packages_count; i++) { - print("#" + attr.packages_index[i]); - tab(); - println("// " + getJavaPackage(attr, i)); - } - indent(-1); - return null; - } - - private String getJavaPackage(ModulePackages_attribute attr, int index) { - try { - return getJavaName(attr.getPackage(index, constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitModuleResolution(ModuleResolution_attribute attr, Void ignore) { - println("ModuleResolution:"); - indent(+1); - print(String.format("%x", attr.resolution_flags)); - tab(); - print("// "); - int flags = attr.resolution_flags; - if ((flags & ModuleResolution_attribute.DO_NOT_RESOLVE_BY_DEFAULT) != 0) - print(" DO_NOT_RESOLVE_BY_DEFAULT"); - if ((flags & ModuleResolution_attribute.WARN_DEPRECATED) != 0) - print(" WARN_DEPRECATED"); - if ((flags & ModuleResolution_attribute.WARN_DEPRECATED_FOR_REMOVAL) != 0) - print(" WARN_DEPRECATED_FOR_REMOVAL"); - if ((flags & ModuleResolution_attribute.WARN_INCUBATING) != 0) - print(" WARN_INCUBATING"); - println(); - indent(-1); - return null; - } - - @Override - public Void visitModuleTarget(ModuleTarget_attribute attr, Void ignore) { - println("ModuleTarget:"); - indent(+1); - print("target_platform: #" + attr.target_platform_index); - if (attr.target_platform_index != 0) { - tab(); - print("// " + getTargetPlatform(attr)); - } - println(); - indent(-1); - return null; - } - - private String getTargetPlatform(ModuleTarget_attribute attr) { - try { - return constant_pool.getUTF8Value(attr.target_platform_index); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitNestMembers(NestMembers_attribute attr, Void aVoid) { - println("NestMembers:"); - indent(+1); - try { - CONSTANT_Class_info[] children = attr.getChildren(constant_pool); - for (int i = 0; i < attr.members_indexes.length; i++) { - println(constantWriter.stringValue(children[i])); - } - indent(-1); - } catch (ConstantPoolException ex) { - throw new AssertionError(ex); - } - return null; - } - - @Override - public Void visitRecord(Record_attribute attr, Void p) { - println("Record:"); - indent(+1); - for (Record_attribute.ComponentInfo componentInfo : attr.component_info_arr) { - Signature_attribute sigAttr = (Signature_attribute) componentInfo.attributes.get(Attribute.Signature); - - if (sigAttr == null) - print(getJavaFieldType(componentInfo.descriptor)); - else { - try { - Type t = sigAttr.getParsedSignature().getType(constant_pool); - print(getJavaName(t.toString())); - } catch (ConstantPoolException e) { - // report error? - // fall back on non-generic descriptor - print(getJavaFieldType(componentInfo.descriptor)); - } - } - - print(" "); - try { - print(componentInfo.getName(constant_pool)); - } catch (ConstantPoolException e) { - report(e); - return null; - } - print(";"); - println(); - indent(+1); - if (options.showDescriptors) { - println("descriptor: " + getValue(componentInfo.descriptor)); - } - if (options.showAllAttrs) { - for (Attribute componentAttr: componentInfo.attributes) - write(componentInfo, componentAttr, constant_pool); - println(); - } - indent(-1); - } - indent(-1); - return null; - } - - String getValue(Descriptor d) { - try { - return d.getValue(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - void writeList(String prefix, Collection items, String suffix) { - print(prefix); - String sep = ""; - for (Object item: items) { - print(sep); - print(item); - sep = ", "; - } - print(suffix); - } - - String getJavaFieldType(Descriptor d) { - try { - return getJavaName(d.getFieldType(constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } catch (InvalidDescriptor e) { - return report(e); - } - } - - void writeModifiers(Collection items) { - for (Object item: items) { - print(item); - print(" "); - } - } - - @Override - public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) { - println("RuntimeVisibleAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - - @Override - public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) { - println("RuntimeInvisibleAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - - @Override - public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { - println("RuntimeVisibleTypeAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - - @Override - public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { - println("RuntimeInvisibleTypeAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - - private void visitParameterAnnotations(String message, RuntimeParameterAnnotations_attribute attr) { + private void printAnnotations(String message, List anno) { println(message); indent(+1); - for (int param = 0; param < attr.parameter_annotations.length; param++) { + for (int i = 0; i < anno.size(); i++) { + print(i + ": "); + annotationWriter.write(anno.get(i)); + println(); + } + indent(-1); + } + + private void printTypeAnnotations(String message, + List anno, CodeAttribute lr) { + println(message); + indent(+1); + for (int i = 0; i < anno.size(); i++) { + print(i + ": "); + annotationWriter.write(anno.get(i), lr); + println(); + } + indent(-1); + } + + private void printParameterAnnotations(String message, List> paramsAnno) { + println(message); + indent(+1); + for (int param = 0; param < paramsAnno.size(); param++) { println("parameter " + param + ": "); indent(+1); - for (int i = 0; i < attr.parameter_annotations[param].length; i++) { + var annos = paramsAnno.get(param); + for (int i = 0; i < annos.size(); i++) { print(i + ": "); - annotationWriter.write(attr.parameter_annotations[param][i]); + annotationWriter.write(annos.get(i)); println(); } indent(-1); @@ -869,247 +678,41 @@ public class AttributeWriter extends BasicWriter indent(-1); } - @Override - public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { - visitParameterAnnotations("RuntimeVisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr); - return null; + void printHeader(int frameType, String extra) { + print("frame_type = " + frameType + " "); + println(extra); } - @Override - public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) { - visitParameterAnnotations("RuntimeInvisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr); - return null; - } - - @Override - public Void visitPermittedSubclasses(PermittedSubclasses_attribute attr, Void ignore) { - println("PermittedSubclasses:"); - indent(+1); - try { - CONSTANT_Class_info[] subtypes = attr.getSubtypes(constant_pool); - for (int i = 0; i < subtypes.length; i++) { - println(constantWriter.stringValue(subtypes[i])); - } - indent(-1); - } catch (ConstantPoolException ex) { - throw new AssertionError(ex); - } - return null; - } - - @Override - public Void visitSignature(Signature_attribute attr, Void ignore) { - print("Signature: #" + attr.signature_index); - tab(); - println("// " + getSignature(attr)); - return null; - } - - String getSignature(Signature_attribute info) { - try { - return info.getSignature(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) { - println("SourceDebugExtension:"); - indent(+1); - for (String s: attr.getValue().split("[\r\n]+")) { - println(s); - } - indent(-1); - return null; - } - - @Override - public Void visitSourceFile(SourceFile_attribute attr, Void ignore) { - println("SourceFile: \"" + getSourceFile(attr) + "\""); - return null; - } - - private String getSourceFile(SourceFile_attribute attr) { - try { - return attr.getSourceFile(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - @Override - public Void visitSourceID(SourceID_attribute attr, Void ignore) { - constantWriter.write(attr.sourceID_index); - return null; - } - - @Override - public Void visitStackMap(StackMap_attribute attr, Void ignore) { - println("StackMap: number_of_entries = " + attr.number_of_entries); - indent(+1); - StackMapTableWriter w = new StackMapTableWriter(); - for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { - w.write(entry); - } - indent(-1); - return null; - } - - @Override - public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) { - println("StackMapTable: number_of_entries = " + attr.number_of_entries); - indent(+1); - StackMapTableWriter w = new StackMapTableWriter(); - for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { - w.write(entry); - } - indent(-1); - return null; - } - - class StackMapTableWriter // also handles CLDC StackMap attributes - implements StackMapTable_attribute.stack_map_frame.Visitor { - public void write(StackMapTable_attribute.stack_map_frame frame) { - frame.accept(this, null); - } - - @Override - public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) { - printHeader(frame, "/* same */"); - return null; - } - - @Override - public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) { - printHeader(frame, "/* same_locals_1_stack_item */"); - indent(+1); - printMap("stack", frame.stack); - indent(-1); - return null; - } - - @Override - public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) { - printHeader(frame, "/* same_locals_1_stack_item_frame_extended */"); - indent(+1); - println("offset_delta = " + frame.offset_delta); - printMap("stack", frame.stack); - indent(-1); - return null; - } - - @Override - public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) { - printHeader(frame, "/* chop */"); - indent(+1); - println("offset_delta = " + frame.offset_delta); - indent(-1); - return null; - } - - @Override - public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) { - printHeader(frame, "/* same_frame_extended */"); - indent(+1); - println("offset_delta = " + frame.offset_delta); - indent(-1); - return null; - } - - @Override - public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) { - printHeader(frame, "/* append */"); - indent(+1); - println("offset_delta = " + frame.offset_delta); - printMap("locals", frame.locals); - indent(-1); - return null; - } - - @Override - public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) { - if (frame instanceof StackMap_attribute.stack_map_frame) { - printHeader(frame, "offset = " + frame.offset_delta); - indent(+1); - } else { - printHeader(frame, "/* full_frame */"); - indent(+1); - println("offset_delta = " + frame.offset_delta); - } - printMap("locals", frame.locals); - printMap("stack", frame.stack); - indent(-1); - return null; - } - - void printHeader(StackMapTable_attribute.stack_map_frame frame, String extra) { - print("frame_type = " + frame.frame_type + " "); - println(extra); - } - - void printMap(String name, StackMapTable_attribute.verification_type_info[] map) { - print(name + " = ["); - for (int i = 0; i < map.length; i++) { - StackMapTable_attribute.verification_type_info info = map[i]; - int tag = info.tag; - switch (tag) { - case StackMapTable_attribute.verification_type_info.ITEM_Object: - print(" "); - constantWriter.write(((StackMapTable_attribute.Object_variable_info) info).cpool_index); - break; - case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: - print(" " + mapTypeName(tag)); - print(" " + ((StackMapTable_attribute.Uninitialized_variable_info) info).offset); - break; - default: - print(" " + mapTypeName(tag)); + void printMap(String name, List map, CodeAttribute lr) { + print(name + " = ["); + for (int i = 0; i < map.size(); i++) { + var info = map.get(i); + switch (info) { + case ObjectVerificationTypeInfo obj -> { + print(" "); + constantWriter.write(obj.className().index()); } - print(i == (map.length - 1) ? " " : ","); - } - println("]"); - } - - String mapTypeName(int tag) { - switch (tag) { - case StackMapTable_attribute.verification_type_info.ITEM_Top: - return "top"; - - case StackMapTable_attribute.verification_type_info.ITEM_Integer: - return "int"; - - case StackMapTable_attribute.verification_type_info.ITEM_Float: - return "float"; - - case StackMapTable_attribute.verification_type_info.ITEM_Long: - return "long"; - - case StackMapTable_attribute.verification_type_info.ITEM_Double: - return "double"; - - case StackMapTable_attribute.verification_type_info.ITEM_Null: - return "null"; - - case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis: - return "this"; - - case StackMapTable_attribute.verification_type_info.ITEM_Object: - return "CP"; - - case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: - return "uninitialized"; - - default: - report("unrecognized verification_type_info tag: " + tag); - return "[tag:" + tag + "]"; + case UninitializedVerificationTypeInfo u -> { + print(" uninitialized " + lr.labelToBci(u.newTarget())); + } + case SimpleVerificationTypeInfo s -> + print(" " + mapTypeName(s)); } + print(i == (map.size() - 1) ? " " : ","); } + println("]"); } - @Override - public Void visitSynthetic(Synthetic_attribute attr, Void ignore) { - println("Synthetic: true"); - return null; + String mapTypeName(SimpleVerificationTypeInfo type) { + return switch (type) { + case ITEM_TOP -> "top"; + case ITEM_INTEGER -> "int"; + case ITEM_FLOAT -> "float"; + case ITEM_LONG -> "long"; + case ITEM_DOUBLE -> "double"; + case ITEM_NULL -> "null"; + case ITEM_UNINITIALIZED_THIS -> "this"; + }; } static String getJavaName(String name) { @@ -1121,14 +724,14 @@ public class AttributeWriter extends BasicWriter } static String toHex(int i) { - return StringUtils.toUpperCase(Integer.toString(i, 16)); + return Integer.toString(i, 16).toUpperCase(Locale.US); } static String toHex(int i, int w) { - String s = StringUtils.toUpperCase(Integer.toHexString(i)); + String s = Integer.toHexString(i).toUpperCase(Locale.US); while (s.length() < w) s = "0" + s; - return StringUtils.toUpperCase(s); + return s; } static String toHex(byte[] ba) { @@ -1143,7 +746,4 @@ public class AttributeWriter extends BasicWriter private final CodeWriter codeWriter; private final ConstantWriter constantWriter; private final Options options; - - private ConstantPool constant_pool; - private Object owner; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/BasicWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/BasicWriter.java index 899bc415125..8629957f907 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/BasicWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/BasicWriter.java @@ -26,10 +26,7 @@ package com.sun.tools.javap; import java.io.PrintWriter; - -import com.sun.tools.classfile.AttributeException; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.DescriptorException; +import java.util.function.Supplier; /* * A writer similar to a PrintWriter but which does not hide exceptions. @@ -57,6 +54,14 @@ public class BasicWriter { lineWriter.print(o == null ? null : o.toString()); } + protected void print(Supplier safeguardedCode) { + try { + print(safeguardedCode.get()); + } catch (IllegalArgumentException e) { + print(report(e)); + } + } + protected void println() { lineWriter.println(); } @@ -71,6 +76,11 @@ public class BasicWriter { lineWriter.println(); } + protected void println(Supplier safeguardedCode) { + print(safeguardedCode); + lineWriter.println(); + } + protected void indent(int delta) { lineWriter.indent(delta); } @@ -83,23 +93,15 @@ public class BasicWriter { lineWriter.pendingNewline = b; } - protected String report(AttributeException e) { - out.println("Error: " + e.getMessage()); // i18n? - return "???"; - } - - protected String report(ConstantPoolException e) { - out.println("Error: " + e.getMessage()); // i18n? - return "???"; - } - - protected String report(DescriptorException e) { + protected String report(Exception e) { out.println("Error: " + e.getMessage()); // i18n? + errorReported = true; return "???"; } protected String report(String msg) { out.println("Error: " + msg); // i18n? + errorReported = true; return "???"; } @@ -123,6 +125,7 @@ public class BasicWriter { private LineWriter lineWriter; private PrintWriter out; protected Messages messages; + protected boolean errorReported; private static class LineWriter { static LineWriter instance(Context context) { diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java index ccd0ea5df53..508fbd9e03a 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java @@ -32,35 +32,23 @@ import java.util.Date; import java.util.List; import java.util.Set; -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Attributes; -import com.sun.tools.classfile.ClassFile; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.ConstantValue_attribute; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.Exceptions_attribute; -import com.sun.tools.classfile.Field; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.Module_attribute; -import com.sun.tools.classfile.Signature; -import com.sun.tools.classfile.Signature_attribute; -import com.sun.tools.classfile.SourceFile_attribute; -import com.sun.tools.classfile.Type; -import com.sun.tools.classfile.Type.ArrayType; -import com.sun.tools.classfile.Type.ClassSigType; -import com.sun.tools.classfile.Type.ClassType; -import com.sun.tools.classfile.Type.MethodType; -import com.sun.tools.classfile.Type.SimpleType; -import com.sun.tools.classfile.Type.TypeParamType; -import com.sun.tools.classfile.Type.WildcardType; - -import static com.sun.tools.classfile.AccessFlags.*; -import static com.sun.tools.classfile.ConstantPool.CONSTANT_Module; -import static com.sun.tools.classfile.ConstantPool.CONSTANT_Package; +import java.lang.constant.ClassDesc; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import jdk.internal.classfile.AccessFlags; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.ClassModel; +import jdk.internal.classfile.ClassSignature; +import jdk.internal.classfile.Classfile; +import static jdk.internal.classfile.Classfile.*; +import jdk.internal.classfile.constantpool.*; +import jdk.internal.classfile.FieldModel; +import jdk.internal.classfile.MethodModel; +import jdk.internal.classfile.MethodSignature; +import jdk.internal.classfile.Signature; +import jdk.internal.classfile.attribute.CodeAttribute; +import jdk.internal.classfile.attribute.SignatureAttribute; /* * The main javap class to write the contents of a class file as text. @@ -85,6 +73,7 @@ public class ClassWriter extends BasicWriter { attrWriter = AttributeWriter.instance(context); codeWriter = CodeWriter.instance(context); constantWriter = ConstantWriter.instance(context); + sigPrinter = new SignaturePrinter(options.verbose); } void setDigest(String name, byte[] digest) { @@ -104,25 +93,25 @@ public class ClassWriter extends BasicWriter { this.lastModified = lastModified; } - protected ClassFile getClassFile() { - return classFile; + protected ClassModel getClassModel() { + return classModel; } - protected void setClassFile(ClassFile cf) { - classFile = cf; - constant_pool = classFile.constant_pool; + protected void setClassFile(ClassModel cm) { + classModel = cm; } - protected Method getMethod() { + protected MethodModel getMethod() { return method; } - protected void setMethod(Method m) { + protected void setMethod(MethodModel m) { method = m; } - public void write(ClassFile cf) { - setClassFile(cf); + public boolean write(ClassModel cm) { + errorReported = false; + setClassFile(cm); if (options.sysInfo || options.verbose) { if (uri != null) { @@ -136,7 +125,8 @@ public class ClassWriter extends BasicWriter { Date lm = new Date(lastModified); DateFormat df = DateFormat.getDateInstance(); if (size > 0) { - println("Last modified " + df.format(lm) + "; size " + size + " bytes"); + println("Last modified " + df.format(lm) + "; size " + size + + " bytes"); } else { println("Last modified " + df.format(lm)); } @@ -151,111 +141,94 @@ public class ClassWriter extends BasicWriter { } } - Attribute sfa = cf.getAttribute(Attribute.SourceFile); - if (sfa instanceof SourceFile_attribute) { - println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\""); - } + cm.findAttribute(Attributes.SOURCE_FILE).ifPresent(sfa -> + println("Compiled from \"" + sfa.sourceFile().stringValue() + "\"")); if (options.sysInfo || options.verbose) { indent(-1); } - AccessFlags flags = cf.access_flags; - writeModifiers(flags.getClassModifiers()); + writeModifiers(getClassModifiers(cm.flags().flagsMask())); - if (classFile.access_flags.is(AccessFlags.ACC_MODULE)) { - Attribute attr = classFile.attributes.get(Attribute.Module); - if (attr instanceof Module_attribute) { - Module_attribute modAttr = (Module_attribute) attr; - String name; - try { - // FIXME: compatibility code - if (constant_pool.get(modAttr.module_name).getTag() == CONSTANT_Module) { - name = getJavaName(constant_pool.getModuleInfo(modAttr.module_name).getName()); - } else { - name = getJavaName(constant_pool.getUTF8Value(modAttr.module_name)); - } - } catch (ConstantPoolException e) { - name = report(e); - } - if ((modAttr.module_flags & Module_attribute.ACC_OPEN) != 0) { + if ((classModel.flags().flagsMask() & ACC_MODULE) != 0) { + var attr = classModel.findAttribute(Attributes.MODULE); + if (attr.isPresent()) { + var modAttr = attr.get(); + if ((modAttr.moduleFlagsMask() & ACC_OPEN) != 0) { print("open "); } print("module "); - print(name); - if (modAttr.module_version_index != 0) { + print(() -> modAttr.moduleName().name().stringValue()); + if (modAttr.moduleVersion().isPresent()) { print("@"); - print(getUTF8Value(modAttr.module_version_index)); + print(() -> modAttr.moduleVersion().get().stringValue()); } } else { // fallback for malformed class files print("class "); - print(getJavaName(classFile)); + print(() -> getJavaName(classModel.thisClass().asInternalName())); } } else { - if (classFile.isClass()) + if ((classModel.flags().flagsMask() & ACC_INTERFACE) == 0) print("class "); - else if (classFile.isInterface()) + else print("interface "); - print(getJavaName(classFile)); + print(() -> getJavaName(classModel.thisClass().asInternalName())); } - Signature_attribute sigAttr = getSignature(cf.attributes); - if (sigAttr == null) { - // use info from class file header - if (classFile.isClass() && classFile.super_class != 0 ) { - String sn = getJavaSuperclassName(cf); - if (!sn.equals("java.lang.Object")) { - print(" extends "); - print(sn); + try { + var sigAttr = classModel.findAttribute(Attributes.SIGNATURE).orElse(null); + if (sigAttr == null) { + // use info from class file header + if ((classModel.flags().flagsMask() & ACC_INTERFACE) == 0 + && classModel.superclass().isPresent()) { + String sn = getJavaName(classModel.superclass().get().asInternalName()); + if (!sn.equals("java.lang.Object")) { + print(" extends "); + print(sn); + } } - } - for (int i = 0; i < classFile.interfaces.length; i++) { - print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ","); - print(getJavaInterfaceName(classFile, i)); - } - } else { - try { - Type t = sigAttr.getParsedSignature().getType(constant_pool); - JavaTypePrinter p = new JavaTypePrinter(classFile.isInterface()); - // The signature parser cannot disambiguate between a - // FieldType and a ClassSignatureType that only contains a superclass type. - if (t instanceof Type.ClassSigType) { - print(p.print(t)); - } else if (options.verbose || !t.isObject()) { - print(" extends "); - print(p.print(t)); + var interfaces = classModel.interfaces(); + for (int i = 0; i < interfaces.size(); i++) { + print(i == 0 ? ((classModel.flags().flagsMask() & ACC_INTERFACE) == 0 + ? " implements " : " extends ") : ","); + print(getJavaName(interfaces.get(i).asInternalName())); } - } catch (ConstantPoolException e) { - print(report(e)); - } catch (IllegalStateException e) { - report("Invalid value for Signature attribute: " + e.getMessage()); + } else { + var t = sigAttr.asClassSignature(); + print(sigPrinter.print(t, (classModel.flags().flagsMask() & ACC_INTERFACE) != 0)); } + } catch (IllegalArgumentException e) { + report(e); } if (options.verbose) { println(); indent(+1); - println("minor version: " + cf.minor_version); - println("major version: " + cf.major_version); - writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getClassFlags(), "\n"); - print("this_class: #" + cf.this_class); - if (cf.this_class != 0) { - tab(); - print("// " + constantWriter.stringValue(cf.this_class)); + println("minor version: " + classModel.minorVersion()); + println("major version: " + classModel.majorVersion()); + writeList(String.format("flags: (0x%04x) ", cm.flags().flagsMask()), + getClassFlags(cm.flags().flagsMask()), "\n"); + print("this_class: #");print(() -> classModel.thisClass().index()); + tab(); + print(() -> "// " + classModel.thisClass().asInternalName()); + println(); + print("super_class: #");print(() -> classModel.superclass() + .map(ClassEntry::index).orElse(0)); + try { + if (classModel.superclass().isPresent()) { + tab(); + print(() -> "// " + classModel.superclass().get().asInternalName()); + } + } catch (IllegalArgumentException e) { + report(e); } println(); - print("super_class: #" + cf.super_class); - if (cf.super_class != 0) { - tab(); - print("// " + constantWriter.stringValue(cf.super_class)); - } - println(); - print("interfaces: " + cf.interfaces.length); - print(", fields: " + cf.fields.length); - print(", methods: " + cf.methods.length); - println(", attributes: " + cf.attributes.attrs.length); + print("interfaces: ");print(() -> classModel.interfaces().size()); + print(", fields: " + classModel.fields().size()); + print(", methods: " + classModel.methods().size()); + println(", attributes: " + classModel.attributes().size()); indent(-1); constantWriter.writeConstantPool(); } else { @@ -264,7 +237,7 @@ public class ClassWriter extends BasicWriter { println("{"); indent(+1); - if (flags.is(AccessFlags.ACC_MODULE) && !options.verbose) { + if ((cm.flags().flagsMask() & ACC_MODULE) != 0 && !options.verbose) { writeDirectives(); } writeFields(); @@ -273,174 +246,166 @@ public class ClassWriter extends BasicWriter { println("}"); if (options.verbose) { - attrWriter.write(cf, cf.attributes, constant_pool); + attrWriter.write(classModel.attributes()); } + return !errorReported; } // where - class JavaTypePrinter implements Type.Visitor { - boolean isInterface; - JavaTypePrinter(boolean isInterface) { - this.isInterface = isInterface; - } + final SignaturePrinter sigPrinter; - String print(Type t) { - return t.accept(this, new StringBuilder()).toString(); - } + public static record SignaturePrinter(boolean verbose) { - String printTypeArgs(List typeParamTypes) { - StringBuilder builder = new StringBuilder(); - appendIfNotEmpty(builder, "<", typeParamTypes, "> "); - return builder.toString(); - } - - @Override - public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) { - sb.append(getJavaName(type.name)); - return sb; - } - - @Override - public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) { - append(sb, type.elemType); - sb.append("[]"); - return sb; - } - - @Override - public StringBuilder visitMethodType(MethodType type, StringBuilder sb) { - appendIfNotEmpty(sb, "<", type.typeParamTypes, "> "); - append(sb, type.returnType); - append(sb, " (", type.paramTypes, ")"); - appendIfNotEmpty(sb, " throws ", type.throwsTypes, ""); - return sb; - } - - @Override - public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) { - appendIfNotEmpty(sb, "<", type.typeParamTypes, ">"); - if (isInterface) { - appendIfNotEmpty(sb, " extends ", type.superinterfaceTypes, ""); - } else { - if (type.superclassType != null - && (options.verbose || !type.superclassType.isObject())) { - sb.append(" extends "); - append(sb, type.superclassType); - } - appendIfNotEmpty(sb, " implements ", type.superinterfaceTypes, ""); - } - return sb; - } - - @Override - public StringBuilder visitClassType(ClassType type, StringBuilder sb) { - if (type.outerType != null) { - append(sb, type.outerType); - sb.append("."); - } - sb.append(getJavaName(type.name)); - appendIfNotEmpty(sb, "<", type.typeArgs, ">"); - return sb; - } - - @Override - public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) { - sb.append(type.name); + public String print(ClassSignature cs, boolean isInterface) { + var sb = new StringBuilder(); + print(sb, cs.typeParameters()); + if (isInterface) { String sep = " extends "; - if (type.classBound != null - && (options.verbose || !type.classBound.isObject())) { + for (var is : cs.superinterfaceSignatures()) { sb.append(sep); - append(sb, type.classBound); - sep = " & "; - } - if (type.interfaceBounds != null) { - for (Type bound: type.interfaceBounds) { - sb.append(sep); - append(sb, bound); - sep = " & "; - } - } - return sb; - } - - @Override - public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) { - switch (type.kind) { - case UNBOUNDED: - sb.append("?"); - break; - case EXTENDS: - sb.append("? extends "); - append(sb, type.boundType); - break; - case SUPER: - sb.append("? super "); - append(sb, type.boundType); - break; - default: - throw new AssertionError(); - } - return sb; - } - - private void append(StringBuilder sb, Type t) { - t.accept(this, sb); - } - - private void append(StringBuilder sb, String prefix, List list, String suffix) { - sb.append(prefix); - String sep = ""; - for (Type t: list) { - sb.append(sep); - append(sb, t); + print(sb, is); + sep = ", "; + } + } else { + if (cs.superclassSignature() != null + && (verbose || !isObject(cs.superclassSignature()))) { + sb.append(" extends "); + print(sb, cs.superclassSignature()); + } + String sep = " implements "; + for (var is : cs.superinterfaceSignatures()) { + sb.append(sep); + print(sb, is); sep = ", "; } - sb.append(suffix); } + return sb.toString(); + } - private void appendIfNotEmpty(StringBuilder sb, String prefix, List list, String suffix) { - if (!isEmpty(list)) - append(sb, prefix, list, suffix); + public String print(Signature sig) { + var sb = new StringBuilder(); + print(sb, sig); + return sb.toString(); + } + + public String printTypeParams(List tps) { + var sb = new StringBuilder(); + print(sb, tps); + return sb.toString(); + } + + public String printList(String prefix, List args, + String postfix) { + var sb = new StringBuilder(); + sb.append(prefix); + String sep = ""; + for (var arg : args) { + sb.append(sep); + print(sb, arg); + sep = ", "; } + return sb.append(postfix).toString(); + } - private boolean isEmpty(List list) { - return (list == null || list.isEmpty()); + private boolean isObject(Signature sig) { + return (sig instanceof Signature.ClassTypeSig cts) + && cts.outerType().isEmpty() + && cts.className().equals("java/lang/Object") + && (cts.typeArgs().isEmpty()); + } + + private void print(StringBuilder sb, List tps) { + if (!tps.isEmpty()) { + sb.append('<'); + String sep = ""; + for (var tp : tps) { + sb.append(sep).append(tp.identifier()); + sep = " extends "; + if (tp.classBound().isPresent() + && (verbose || !isObject(tp.classBound().get()))) { + sb.append(sep); + print(sb, tp.classBound().get()); + sep = " & "; + } + for (var bound: tp.interfaceBounds()) { + sb.append(sep); + print(sb, bound); + sep = " & "; + } + sep = ", "; + } + sb.append('>'); } } + private void print(StringBuilder sb, Signature sig) { + if (sig instanceof Signature.BaseTypeSig bts) { + sb.append(ClassDesc.ofDescriptor("" + bts.baseType()).displayName()); + } else if (sig instanceof Signature.ClassTypeSig cts) { + if (cts.outerType().isPresent()) { + print(sb, cts.outerType().get()); + sb.append("."); + } + sb.append(getJavaName(cts.className())); + if (!cts.typeArgs().isEmpty()) { + String sep = ""; + sb.append('<'); + for (var ta : cts.typeArgs()) { + sb.append(sep); + print(sb, ta); + sep = ", "; + } + sb.append('>'); + } + } else if (sig instanceof Signature.TypeVarSig tvs) { + sb.append(tvs.identifier()); + } else if (sig instanceof Signature.ArrayTypeSig ats) { + print(sb, ats.componentSignature()); + sb.append("[]"); + } + } + + private void print(StringBuilder sb, Signature.TypeArg ta) { + switch (ta.wildcardIndicator()) { + case DEFAULT -> print(sb, ta.boundType().get()); + case UNBOUNDED -> sb.append('?'); + case EXTENDS -> { + sb.append("? extends "); + print(sb, ta.boundType().get()); + } + case SUPER -> { + sb.append("? super "); + print(sb, ta.boundType().get()); + } + } + } + } + protected void writeFields() { - for (Field f: classFile.fields) { + for (var f: classModel.fields()) { writeField(f); } } - protected void writeField(Field f) { - if (!options.checkAccess(f.access_flags)) + protected void writeField(FieldModel f) { + if (!options.checkAccess(f.flags().flagsMask())) return; - AccessFlags flags = f.access_flags; - writeModifiers(flags.getFieldModifiers()); - Signature_attribute sigAttr = getSignature(f.attributes); - if (sigAttr == null) - print(getJavaFieldType(f.descriptor)); - else { - try { - Type t = sigAttr.getParsedSignature().getType(constant_pool); - print(getJavaName(t.toString())); - } catch (ConstantPoolException e) { - // report error? - // fall back on non-generic descriptor - print(getJavaFieldType(f.descriptor)); - } - } + var flags = AccessFlags.ofField(f.flags().flagsMask()); + writeModifiers(flags.flags().stream().filter(fl -> fl.sourceModifier()) + .map(fl -> Modifier.toString(fl.mask())).toList()); + print(() -> sigPrinter.print( + f.findAttribute(Attributes.SIGNATURE) + .map(SignatureAttribute::asTypeSignature) + .orElseGet(() -> Signature.of(f.fieldTypeSymbol())))); print(" "); - print(getFieldName(f)); + print(() -> f.fieldName().stringValue()); if (options.showConstants) { - Attribute a = f.attributes.get(Attribute.ConstantValue); - if (a instanceof ConstantValue_attribute) { + var a = f.findAttribute(Attributes.CONSTANT_VALUE); + if (a.isPresent()) { print(" = "); - ConstantValue_attribute cv = (ConstantValue_attribute) a; - print(getConstantValue(f.descriptor, cv.constantvalue_index)); + var cv = a.get(); + print(() -> getConstantValue(f.fieldTypeSymbol(), cv.constant())); } } print(";"); @@ -450,15 +415,17 @@ public class ClassWriter extends BasicWriter { boolean showBlank = false; - if (options.showDescriptors) - println("descriptor: " + getValue(f.descriptor)); + if (options.showDescriptors) { + print("descriptor: ");println(() -> f.fieldType().stringValue()); + } if (options.verbose) - writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getFieldFlags(), "\n"); + writeList(String.format("flags: (0x%04x) ", flags.flagsMask()), + flags.flags().stream().map(fl -> "ACC_" + fl.name()).toList(), + "\n"); if (options.showAllAttrs) { - for (Attribute attr: f.attributes) - attrWriter.write(f, attr, constant_pool); + attrWriter.write(f.attributes()); showBlank = true; } @@ -469,7 +436,7 @@ public class ClassWriter extends BasicWriter { } protected void writeMethods() { - for (Method m: classFile.methods) + for (MethodModel m: classModel.methods()) writeMethod(m); setPendingNewline(false); } @@ -477,89 +444,84 @@ public class ClassWriter extends BasicWriter { private static final int DEFAULT_ALLOWED_MAJOR_VERSION = 52; private static final int DEFAULT_ALLOWED_MINOR_VERSION = 0; - protected void writeMethod(Method m) { - if (!options.checkAccess(m.access_flags)) + protected void writeMethod(MethodModel m) { + if (!options.checkAccess(m.flags().flagsMask())) return; method = m; - AccessFlags flags = m.access_flags; + int flags = m.flags().flagsMask(); - Descriptor d; - Type.MethodType methodType; - List methodExceptions; + var modifiers = new ArrayList(); + for (var f : AccessFlags.ofMethod(flags).flags()) + if (f.sourceModifier()) modifiers.add(Modifier.toString(f.mask())); - Signature_attribute sigAttr = getSignature(m.attributes); - if (sigAttr == null) { - d = m.descriptor; - methodType = null; - methodExceptions = null; - } else { - Signature methodSig = sigAttr.getParsedSignature(); - d = methodSig; - try { - methodType = (Type.MethodType) methodSig.getType(constant_pool); - methodExceptions = methodType.throwsTypes; - if (methodExceptions != null && methodExceptions.isEmpty()) - methodExceptions = null; - } catch (ConstantPoolException | IllegalStateException e) { - // report error? - // fall back on standard descriptor - methodType = null; - methodExceptions = null; - } + String name = "???"; + try { + name = m.methodName().stringValue(); + } catch (IllegalArgumentException e) { + report(e); } - Set modifiers = flags.getMethodModifiers(); - - String name = getName(m); - if (classFile.isInterface() && - (!flags.is(AccessFlags.ACC_ABSTRACT)) && !name.equals("")) { - if (classFile.major_version > DEFAULT_ALLOWED_MAJOR_VERSION || - (classFile.major_version == DEFAULT_ALLOWED_MAJOR_VERSION && classFile.minor_version >= DEFAULT_ALLOWED_MINOR_VERSION)) { - if (!flags.is(AccessFlags.ACC_STATIC | AccessFlags.ACC_PRIVATE)) { + if ((classModel.flags().flagsMask() & ACC_INTERFACE) != 0 && + ((flags & ACC_ABSTRACT) == 0) && !name.equals("")) { + if (classModel.majorVersion() > DEFAULT_ALLOWED_MAJOR_VERSION || + (classModel.majorVersion() == DEFAULT_ALLOWED_MAJOR_VERSION + && classModel.minorVersion() >= DEFAULT_ALLOWED_MINOR_VERSION)) { + if ((flags & (ACC_STATIC | ACC_PRIVATE)) == 0) { modifiers.add("default"); } } } - writeModifiers(modifiers); - if (methodType != null) { - print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes)); - } - switch (name) { - case "": - print(getJavaName(classFile)); - print(getJavaParameterTypes(d, flags)); - break; - case "": - print("{}"); - break; - default: - print(getJavaReturnType(d)); - print(" "); - print(name); - print(getJavaParameterTypes(d, flags)); - break; - } - Attribute e_attr = m.attributes.get(Attribute.Exceptions); - if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions - if (e_attr instanceof Exceptions_attribute) { - Exceptions_attribute exceptions = (Exceptions_attribute) e_attr; + try { + var sigAttr = m.findAttribute(Attributes.SIGNATURE); + MethodSignature d; + if (sigAttr.isEmpty()) { + d = MethodSignature.parseFrom(m.methodType().stringValue()); + } else { + d = sigAttr.get().asMethodSignature(); + } + + if (!d.typeParameters().isEmpty()) { + print(sigPrinter.printTypeParams(d.typeParameters()) + " "); + } + switch (name) { + case "": + print(getJavaName(classModel.thisClass().asInternalName())); + print(getJavaParameterTypes(d, flags)); + break; + case "": + print("{}"); + break; + default: + print(getJavaName(sigPrinter.print(d.result()))); + print(" "); + print(name); + print(getJavaParameterTypes(d, flags)); + break; + } + + var e_attr = m.findAttribute(Attributes.EXCEPTIONS); + // if there are generic exceptions, there must be erased exceptions + if (e_attr.isPresent()) { + var exceptions = e_attr.get(); print(" throws "); - if (methodExceptions != null) { // use generic list if available - writeList("", methodExceptions, ""); + if (d != null && !d.throwableSignatures().isEmpty()) { // use generic list if available + print(() -> sigPrinter.printList("", d.throwableSignatures(), "")); } else { - for (int i = 0; i < exceptions.number_of_exceptions; i++) { + var exNames = exceptions.exceptions(); + for (int i = 0; i < exNames.size(); i++) { if (i > 0) print(", "); - print(getJavaException(exceptions, i)); + int ii = i; + print(() -> getJavaName(exNames.get(ii).asInternalName())); } } - } else { - report("Unexpected or invalid value for Exceptions attribute"); } + } catch (IllegalArgumentException e) { + report(e); } println(";"); @@ -567,26 +529,24 @@ public class ClassWriter extends BasicWriter { indent(+1); if (options.showDescriptors) { - println("descriptor: " + getValue(m.descriptor)); + print("descriptor: ");println(() -> m.methodType().stringValue()); } if (options.verbose) { - writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getMethodFlags(), "\n"); + StringBuilder sb = new StringBuilder(); + String sep = ""; + sb.append(String.format("flags: (0x%04x) ", flags)); + for (var f : AccessFlags.ofMethod(flags).flags()) { + sb.append(sep).append("ACC_").append(f.name()); + sep = ", "; + } + println(sb.toString()); } - Code_attribute code = null; - Attribute c_attr = m.attributes.get(Attribute.Code); - if (c_attr != null) { - if (c_attr instanceof Code_attribute) - code = (Code_attribute) c_attr; - else - report("Unexpected or invalid value for Code attribute"); - } + var code = (CodeAttribute)m.code().orElse(null); if (options.showAllAttrs) { - Attribute[] attrs = m.attributes.attrs; - for (Attribute attr: attrs) - attrWriter.write(m, attr, constant_pool); + attrWriter.write(m.attributes()); } else if (code != null) { if (options.showDisassembled) { println("Code:"); @@ -595,8 +555,10 @@ public class ClassWriter extends BasicWriter { } if (options.showLineAndLocalVariableTables) { - attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool); - attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool); + code.findAttribute(Attributes.LINE_NUMBER_TABLE) + .ifPresent(a -> attrWriter.write(a, code)); + code.findAttribute(Attributes.LOCAL_VARIABLE_TABLE) + .ifPresent(a -> attrWriter.write(a, code)); } } @@ -619,47 +581,33 @@ public class ClassWriter extends BasicWriter { } } + public static final int ACC_TRANSITIVE = 0x0020; + public static final int ACC_STATIC_PHASE = 0x0040; + void writeDirectives() { - Attribute attr = classFile.attributes.get(Attribute.Module); - if (!(attr instanceof Module_attribute)) + var attr = classModel.findAttribute(Attributes.MODULE); + if (attr.isEmpty()) return; - Module_attribute m = (Module_attribute) attr; - for (Module_attribute.RequiresEntry entry: m.requires) { + var m = attr.get(); + for (var entry: m.requires()) { print("requires"); - if ((entry.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0) + if ((entry.requiresFlagsMask() & ACC_STATIC_PHASE) != 0) print(" static"); - if ((entry.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0) + if ((entry.requiresFlagsMask() & ACC_TRANSITIVE) != 0) print(" transitive"); print(" "); String mname; - try { - mname = getModuleName(entry.requires_index); - } catch (ConstantPoolException e) { - mname = report(e); - } - print(mname); + print(entry.requires().name().stringValue()); println(";"); } - for (Module_attribute.ExportsEntry entry: m.exports) { + for (var entry: m.exports()) { print("exports"); print(" "); - String pname; - try { - pname = getPackageName(entry.exports_index).replace('/', '.'); - } catch (ConstantPoolException e) { - pname = report(e); - } - print(pname); + print(entry.exportedPackage().name().stringValue().replace('/', '.')); boolean first = true; - for (int i: entry.exports_to_index) { - String mname; - try { - mname = getModuleName(i); - } catch (ConstantPoolException e) { - mname = report(e); - } + for (var mod: entry.exportsTo()) { if (first) { println(" to"); indent(+1); @@ -667,31 +615,19 @@ public class ClassWriter extends BasicWriter { } else { println(","); } - print(mname); + print(mod.name().stringValue()); } println(";"); if (!first) indent(-1); } - for (Module_attribute.OpensEntry entry: m.opens) { + for (var entry: m.opens()) { print("opens"); print(" "); - String pname; - try { - pname = getPackageName(entry.opens_index).replace('/', '.'); - } catch (ConstantPoolException e) { - pname = report(e); - } - print(pname); + print(entry.openedPackage().name().stringValue().replace('/', '.')); boolean first = true; - for (int i: entry.opens_to_index) { - String mname; - try { - mname = getModuleName(i); - } catch (ConstantPoolException e) { - mname = report(e); - } + for (var mod: entry.opensTo()) { if (first) { println(" to"); indent(+1); @@ -699,24 +635,24 @@ public class ClassWriter extends BasicWriter { } else { println(","); } - print(mname); + print(mod.name().stringValue()); } println(";"); if (!first) indent(-1); } - for (int entry: m.uses_index) { + for (var entry: m.uses()) { print("uses "); - print(getClassName(entry).replace('/', '.')); + print(entry.asInternalName().replace('/', '.')); println(";"); } - for (Module_attribute.ProvidesEntry entry: m.provides) { + for (var entry: m.provides()) { print("provides "); - print(getClassName(entry.provides_index).replace('/', '.')); + print(entry.provides().asInternalName().replace('/', '.')); boolean first = true; - for (int i: entry.with_index) { + for (var ce: entry.providesWith()) { if (first) { println(" with"); indent(+1); @@ -724,7 +660,7 @@ public class ClassWriter extends BasicWriter { } else { println(","); } - print(getClassName(i).replace('/', '.')); + print(ce.asInternalName().replace('/', '.')); } println(";"); if (!first) @@ -732,38 +668,6 @@ public class ClassWriter extends BasicWriter { } } - String getModuleName(int index) throws ConstantPoolException { - if (constant_pool.get(index).getTag() == CONSTANT_Module) { - return constant_pool.getModuleInfo(index).getName(); - } else { - return constant_pool.getUTF8Value(index); - } - } - - String getPackageName(int index) throws ConstantPoolException { - if (constant_pool.get(index).getTag() == CONSTANT_Package) { - return constant_pool.getPackageInfo(index).getName(); - } else { - return constant_pool.getUTF8Value(index); - } - } - - String getUTF8Value(int index) { - try { - return classFile.constant_pool.getUTF8Value(index); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getClassName(int index) { - try { - return classFile.constant_pool.getClassInfo(index).getName(); - } catch (ConstantPoolException e) { - return report(e); - } - } - void writeList(String prefix, Collection items, String suffix) { print(prefix); String sep = ""; @@ -780,12 +684,8 @@ public class ClassWriter extends BasicWriter { writeList(prefix, items, suffix); } - Signature_attribute getSignature(Attributes attributes) { - return (Signature_attribute) attributes.get(Attribute.Signature); - } - - String adjustVarargs(AccessFlags flags, String params) { - if (flags.is(ACC_VARARGS)) { + String adjustVarargs(int flags, String params) { + if ((flags & ACC_VARARGS) != 0) { int i = params.lastIndexOf("[]"); if (i > 0) return params.substring(0, i) + "..." + params.substring(i+2); @@ -794,104 +694,15 @@ public class ClassWriter extends BasicWriter { return params; } - String getJavaName(ClassFile cf) { - try { - return getJavaName(cf.getName()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getJavaSuperclassName(ClassFile cf) { - try { - return getJavaName(cf.getSuperclassName()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getJavaInterfaceName(ClassFile cf, int index) { - try { - return getJavaName(cf.getInterfaceName(index)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getJavaFieldType(Descriptor d) { - try { - return getJavaName(d.getFieldType(constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } catch (InvalidDescriptor e) { - return report(e); - } - } - - String getJavaReturnType(Descriptor d) { - try { - return getJavaName(d.getReturnType(constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } catch (InvalidDescriptor e) { - return report(e); - } - } - - String getJavaParameterTypes(Descriptor d, AccessFlags flags) { - try { - return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool))); - } catch (ConstantPoolException e) { - return report(e); - } catch (InvalidDescriptor e) { - return report(e); - } - } - - String getJavaException(Exceptions_attribute attr, int index) { - try { - return getJavaName(attr.getException(index, constant_pool)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getValue(Descriptor d) { - try { - return d.getValue(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getFieldName(Field f) { - try { - return f.getName(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getName(Method m) { - try { - return m.getName(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } + String getJavaParameterTypes(MethodSignature d, int flags) { + return getJavaName(adjustVarargs(flags, + sigPrinter.printList("(", d.arguments(), ")"))); } static String getJavaName(String name) { return name.replace('/', '.'); } - String getSourceFile(SourceFile_attribute attr) { - try { - return attr.getSourceFile(constant_pool); - } catch (ConstantPoolException e) { - return report(e); - } - } - /** * Get the value of an entry in the constant pool as a Java constant. * Characters and booleans are represented by CONSTANT_Intgere entries. @@ -901,39 +712,26 @@ public class ClassWriter extends BasicWriter { * @param index the index of the value in the constant pool * @return a printable string containing the value of the constant. */ - String getConstantValue(Descriptor d, int index) { - try { - ConstantPool.CPInfo cpInfo = constant_pool.get(index); - - switch (cpInfo.getTag()) { - case ConstantPool.CONSTANT_Integer: { - ConstantPool.CONSTANT_Integer_info info = - (ConstantPool.CONSTANT_Integer_info) cpInfo; - String t = d.getValue(constant_pool); - switch (t) { - case "C": - // character - return getConstantCharValue((char) info.value); - case "Z": - // boolean - return String.valueOf(info.value == 1); - default: - // other: assume integer - return String.valueOf(info.value); - } + String getConstantValue(ClassDesc d, ConstantValueEntry cpInfo) { + switch (cpInfo.tag()) { + case Classfile.TAG_INTEGER: { + var val = (Integer)cpInfo.constantValue(); + switch (d.descriptorString()) { + case "C": + // character + return getConstantCharValue((char)val.intValue()); + case "Z": + // boolean + return String.valueOf(val == 1); + default: + // other: assume integer + return String.valueOf(val); } - - case ConstantPool.CONSTANT_String: { - ConstantPool.CONSTANT_String_info info = - (ConstantPool.CONSTANT_String_info) cpInfo; - return getConstantStringValue(info.getString()); - } - - default: - return constantWriter.stringValue(cpInfo); } - } catch (ConstantPoolException e) { - return "#" + index; + case Classfile.TAG_STRING: + return getConstantStringValue(cpInfo.constantValue().toString()); + default: + return constantWriter.stringValue(cpInfo); } } @@ -971,16 +769,97 @@ public class ClassWriter extends BasicWriter { } } + private static Set getClassModifiers(int mask) { + return getModifiers(AccessFlags.ofClass((mask & ACC_INTERFACE) != 0 + ? mask & ~ACC_ABSTRACT : mask).flags()); + } + + private static Set getMethodModifiers(int mask) { + return getModifiers(AccessFlags.ofMethod(mask).flags()); + } + + private static Set getFieldModifiers(int mask) { + return getModifiers(AccessFlags.ofField(mask).flags()); + } + + private static Set getModifiers(Set flags) { + Set s = new LinkedHashSet<>(); + for (var f : flags) + if (f.sourceModifier()) s.add(Modifier.toString(f.mask())); + return s; + } + + private static Set getClassFlags(int mask) { + return getFlags(mask, AccessFlags.ofClass(mask).flags()); + } + + private static Set getMethodFlags(int mask) { + return getFlags(mask, AccessFlags.ofMethod(mask).flags()); + } + + private static Set getFieldFlags(int mask) { + return getFlags(mask, AccessFlags.ofField(mask).flags()); + } + + private static Set getFlags(int mask, Set flags) { + Set s = new LinkedHashSet<>(); + for (var f: flags) { + s.add("ACC_" + f.name()); + mask = mask & ~f.mask(); + } + while (mask != 0) { + int bit = Integer.highestOneBit(mask); + s.add("0x" + Integer.toHexString(bit)); + mask = mask & ~bit; + } + return s; + } + + public static enum AccessFlag { + ACC_PUBLIC (Classfile.ACC_PUBLIC, "public", true, true, true, true ), + ACC_PRIVATE (Classfile.ACC_PRIVATE, "private", false, true, true, true ), + ACC_PROTECTED (Classfile.ACC_PROTECTED, "protected", false, true, true, true ), + ACC_STATIC (Classfile.ACC_STATIC, "static", false, true, true, true ), + ACC_FINAL (Classfile.ACC_FINAL, "final", true, true, true, true ), + ACC_SUPER (Classfile.ACC_SUPER, null, true, false, false, false), + ACC_SYNCHRONIZED(Classfile.ACC_SYNCHRONIZED, "synchronized", false, false, false, true ), + ACC_VOLATILE (Classfile.ACC_VOLATILE, "volatile", false, false, true, false), + ACC_BRIDGE (Classfile.ACC_BRIDGE, null, false, false, false, true ), + ACC_TRANSIENT (Classfile.ACC_TRANSIENT, "transient", false, false, true, false), + ACC_VARARGS (Classfile.ACC_VARARGS, null, false, false, false, true ), + ACC_NATIVE (Classfile.ACC_NATIVE, "native", false, false, false, true ), + ACC_INTERFACE (Classfile.ACC_INTERFACE, null, true, true, false, false), + ACC_ABSTRACT (Classfile.ACC_ABSTRACT, "abstract", true, true, false, true ), + ACC_STRICT (Classfile.ACC_STRICT, "strictfp", false, false, false, true ), + ACC_SYNTHETIC (Classfile.ACC_SYNTHETIC, null, true, true, true, true ), + ACC_ANNOTATION (Classfile.ACC_ANNOTATION, null, true, true, false, false), + ACC_ENUM (Classfile.ACC_ENUM, null, true, true, true, false), + ACC_MODULE (Classfile.ACC_MODULE, null, true, false, false, false); + + public final int flag; + public final String modifier; + public final boolean isClass, isInnerClass, isField, isMethod; + + AccessFlag(int flag, String modifier, boolean isClass, + boolean isInnerClass, boolean isField, boolean isMethod) { + this.flag = flag; + this.modifier = modifier; + this.isClass = isClass; + this.isInnerClass = isInnerClass; + this.isField = isField; + this.isMethod = isMethod; + } + } + private final Options options; private final AttributeWriter attrWriter; private final CodeWriter codeWriter; private final ConstantWriter constantWriter; - private ClassFile classFile; + private ClassModel classModel; private URI uri; private long lastModified; private String digestName; private byte[] digest; private int size; - private ConstantPool constant_pool; - private Method method; + private MethodModel method; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java index 231706c6900..64e947b9992 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java @@ -28,14 +28,15 @@ package com.sun.tools.javap; import java.util.ArrayList; import java.util.List; -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.DescriptorException; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.Instruction.TypeKind; -import com.sun.tools.classfile.Method; +import java.util.Locale; +import java.util.stream.Collectors; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.Opcode; +import jdk.internal.classfile.constantpool.*; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.MethodModel; +import jdk.internal.classfile.attribute.CodeAttribute; +import jdk.internal.classfile.instruction.*; /* * Write the contents of a Code attribute. @@ -68,161 +69,148 @@ public class CodeWriter extends BasicWriter { options = Options.instance(context); } - void write(Code_attribute attr, ConstantPool constant_pool) { + void write(CodeAttribute attr) { println("Code:"); indent(+1); - writeVerboseHeader(attr, constant_pool); + writeVerboseHeader(attr); writeInstrs(attr); writeExceptionTable(attr); - attrWriter.write(attr, attr.attributes, constant_pool); + attrWriter.write(attr.attributes(), attr); indent(-1); } - public void writeVerboseHeader(Code_attribute attr, ConstantPool constant_pool) { - Method method = classWriter.getMethod(); - String argCount; - try { - int n = method.descriptor.getParameterCount(constant_pool); - if (!method.access_flags.is(AccessFlags.ACC_STATIC)) - ++n; // for 'this' - argCount = Integer.toString(n); - } catch (ConstantPoolException e) { - argCount = report(e); - } catch (DescriptorException e) { - argCount = report(e); - } - - println("stack=" + attr.max_stack + - ", locals=" + attr.max_locals + - ", args_size=" + argCount); - + public void writeVerboseHeader(CodeAttribute attr) { + MethodModel method = attr.parent().get(); + int n = method.methodTypeSymbol().parameterCount(); + if ((method.flags().flagsMask() & Classfile.ACC_STATIC) == 0) + ++n; // for 'this' + println("stack=" + attr.maxStack() + + ", locals=" + attr.maxLocals() + + ", args_size=" + Integer.toString(n)); } - public void writeInstrs(Code_attribute attr) { + public void writeInstrs(CodeAttribute attr) { List detailWriters = getDetailWriters(attr); - for (Instruction instr: attr.getInstructions()) { - try { - for (InstructionDetailWriter w: detailWriters) - w.writeDetails(instr); - writeInstr(instr); - } catch (ArrayIndexOutOfBoundsException | IllegalStateException e) { - println(report("error at or after byte " + instr.getPC())); - break; + int pc = 0; + try { + for (var coe: attr) { + if (coe instanceof Instruction instr) { + for (InstructionDetailWriter w: detailWriters) + w.writeDetails(pc, instr); + writeInstr(pc, instr, attr); + pc += instr.sizeInBytes(); + } } + } catch (IllegalArgumentException e) { + report("error at or after byte " + pc); } for (InstructionDetailWriter w: detailWriters) - w.flush(); + w.flush(pc); } - public void writeInstr(Instruction instr) { - print(String.format("%4d: %-13s ", instr.getPC(), instr.getMnemonic())); - // compute the number of indentations for the body of multi-line instructions - // This is 6 (the width of "%4d: "), divided by the width of each indentation level, - // and rounded up to the next integer. - int indentWidth = options.indentWidth; - int indent = (6 + indentWidth - 1) / indentWidth; - instr.accept(instructionPrinter, indent); - println(); + public void writeInstr(int pc, Instruction ins, CodeAttribute lr) { + print(String.format("%4d: %-13s ", pc, ins.opcode().name().toLowerCase(Locale.US))); + try { + // compute the number of indentations for the body of multi-line instructions + // This is 6 (the width of "%4d: "), divided by the width of each indentation level, + // and rounded up to the next integer. + int indentWidth = options.indentWidth; + int indent = (6 + indentWidth - 1) / indentWidth; + switch (ins) { + case BranchInstruction instr -> + print(lr.labelToBci(instr.target())); + case ConstantInstruction.ArgumentConstantInstruction instr -> + print(instr.constantValue()); + case ConstantInstruction.LoadConstantInstruction instr -> + printConstantPoolRef(instr.constantEntry()); + case FieldInstruction instr -> + printConstantPoolRef(instr.field()); + case InvokeDynamicInstruction instr -> + printConstantPoolRefAndValue(instr.invokedynamic(), 0); + case InvokeInstruction instr -> { + if (instr.isInterface() && instr.opcode() != Opcode.INVOKESTATIC) + printConstantPoolRefAndValue(instr.method(), instr.count()); + else printConstantPoolRef(instr.method()); + } + case LoadInstruction instr -> + print(instr.sizeInBytes() > 1 ? instr.slot() : ""); + case StoreInstruction instr -> + print(instr.sizeInBytes() > 1 ? instr.slot() : ""); + case IncrementInstruction instr -> + print(instr.slot() + ", " + instr.constant()); + case LookupSwitchInstruction instr -> { + var cases = instr.cases(); + print("{ // " + cases.size()); + indent(indent); + for (var c : cases) + print(String.format("%n%12d: %d", c.caseValue(), + lr.labelToBci(c.target()))); + print("\n default: " + lr.labelToBci(instr.defaultTarget()) + "\n}"); + indent(-indent); + } + case NewMultiArrayInstruction instr -> + printConstantPoolRefAndValue(instr.arrayType(), instr.dimensions()); + case NewObjectInstruction instr -> + printConstantPoolRef(instr.className()); + case NewPrimitiveArrayInstruction instr -> + print(" " + instr.typeKind().typeName()); + case NewReferenceArrayInstruction instr -> + printConstantPoolRef(instr.componentType()); + case TableSwitchInstruction instr -> { + print("{ // " + instr.lowValue() + " to " + instr.highValue()); + indent(indent); + var caseMap = instr.cases().stream().collect( + Collectors.toMap(SwitchCase::caseValue, SwitchCase::target)); + for (int i = instr.lowValue(); i <= instr.highValue(); i++) + print(String.format("%n%12d: %d", i, + lr.labelToBci(caseMap.getOrDefault(i, instr.defaultTarget())))); + print("\n default: " + lr.labelToBci(instr.defaultTarget()) + "\n}"); + indent(-indent); + } + case TypeCheckInstruction instr -> + printConstantPoolRef(instr.type()); + default -> {} + } + println(); + } catch (IllegalArgumentException e) { + println(report(e)); + } } - // where - Instruction.KindVisitor instructionPrinter = - new Instruction.KindVisitor<>() { - public Void visitNoOperands(Instruction instr, Integer indent) { - return null; - } + private void printConstantPoolRef(PoolEntry entry) { + print("#" + entry.index()); + tab(); + print("// "); + constantWriter.write(entry.index()); + } - public Void visitArrayType(Instruction instr, TypeKind kind, Integer indent) { - print(" " + kind.name); - return null; - } + private void printConstantPoolRefAndValue(PoolEntry entry, int value) { + print("#" + entry.index() + ", " + value); + tab(); + print("// "); + constantWriter.write(entry.index()); + } - public Void visitBranch(Instruction instr, int offset, Integer indent) { - print((instr.getPC() + offset)); - return null; - } - - public Void visitConstantPoolRef(Instruction instr, int index, Integer indent) { - print("#" + index); - tab(); - print("// "); - printConstant(index); - return null; - } - - public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Integer indent) { - print("#" + index + ", " + value); - tab(); - print("// "); - printConstant(index); - return null; - } - - public Void visitLocal(Instruction instr, int index, Integer indent) { - print(index); - return null; - } - - public Void visitLocalAndValue(Instruction instr, int index, int value, Integer indent) { - print(index + ", " + value); - return null; - } - - public Void visitLookupSwitch(Instruction instr, - int default_, int npairs, int[] matches, int[] offsets, Integer indent) { - int pc = instr.getPC(); - print("{ // " + npairs); - indent(indent); - for (int i = 0; i < npairs; i++) { - print(String.format("%n%12d: %d", matches[i], (pc + offsets[i]))); - } - print("\n default: " + (pc + default_) + "\n}"); - indent(-indent); - return null; - } - - public Void visitTableSwitch(Instruction instr, - int default_, int low, int high, int[] offsets, Integer indent) { - int pc = instr.getPC(); - print("{ // " + low + " to " + high); - indent(indent); - for (int i = 0; i < offsets.length; i++) { - print(String.format("%n%12d: %d", (low + i), (pc + offsets[i]))); - } - print("\n default: " + (pc + default_) + "\n}"); - indent(-indent); - return null; - } - - public Void visitValue(Instruction instr, int value, Integer indent) { - print(value); - return null; - } - - public Void visitUnknown(Instruction instr, Integer indent) { - return null; - } - }; - - - public void writeExceptionTable(Code_attribute attr) { - if (attr.exception_table_length > 0) { + public void writeExceptionTable(CodeAttribute attr) { + var excTable = attr.exceptionHandlers(); + if (excTable.size() > 0) { println("Exception table:"); indent(+1); println(" from to target type"); - for (int i = 0; i < attr.exception_table.length; i++) { - Code_attribute.Exception_data handler = attr.exception_table[i]; + for (var handler : excTable) { print(String.format(" %5d %5d %5d", - handler.start_pc, handler.end_pc, handler.handler_pc)); + attr.labelToBci(handler.tryStart()), + attr.labelToBci(handler.tryEnd()), + attr.labelToBci(handler.handler()))); print(" "); - int catch_type = handler.catch_type; - if (catch_type == 0) { + var catch_type = handler.catchType(); + if (catch_type.isEmpty()) { println("any"); } else { print("Class "); - println(constantWriter.stringValue(catch_type)); + println(constantWriter.stringValue(catch_type.get())); } } indent(-1); @@ -230,14 +218,10 @@ public class CodeWriter extends BasicWriter { } - private void printConstant(int index) { - constantWriter.write(index); - } - - private List getDetailWriters(Code_attribute attr) { + private List getDetailWriters(CodeAttribute attr) { List detailWriters = new ArrayList<>(); if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) { - sourceWriter.reset(classWriter.getClassFile(), attr); + sourceWriter.reset(attr); if (sourceWriter.hasSource()) detailWriters.add(sourceWriter); else diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java index 59f8c4e935c..096ca97e0b6 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java @@ -25,11 +25,8 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.ClassFile; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; - -import static com.sun.tools.classfile.ConstantPool.*; +import jdk.internal.classfile.constantpool.*; +import static jdk.internal.classfile.Classfile.*; /* * Write a constant pool entry. @@ -55,122 +52,11 @@ public class ConstantWriter extends BasicWriter { } protected void writeConstantPool() { - ConstantPool constant_pool = classWriter.getClassFile().constant_pool; + var constant_pool = classWriter.getClassModel().constantPool(); writeConstantPool(constant_pool); } protected void writeConstantPool(ConstantPool constant_pool) { - ConstantPool.Visitor v = new ConstantPool.Visitor<>() { - public Integer visitClass(CONSTANT_Class_info info, Void p) { - print("#" + info.name_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitDouble(CONSTANT_Double_info info, Void p) { - println(stringValue(info)); - return 2; - } - - public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) { - print("#" + info.class_index + ".#" + info.name_and_type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitFloat(CONSTANT_Float_info info, Void p) { - println(stringValue(info)); - return 1; - } - - public Integer visitInteger(CONSTANT_Integer_info info, Void p) { - println(stringValue(info)); - return 1; - } - - public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { - print("#" + info.class_index + ".#" + info.name_and_type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) { - print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) { - print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitLong(CONSTANT_Long_info info, Void p) { - println(stringValue(info)); - return 2; - } - - public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) { - print("#" + info.class_index + ".#" + info.name_and_type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) { - print(info.reference_kind.tag + ":#" + info.reference_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitMethodType(CONSTANT_MethodType_info info, Void p) { - print("#" + info.descriptor_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitModule(CONSTANT_Module_info info, Void p) { - print("#" + info.name_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) { - print("#" + info.name_index + ":#" + info.type_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitPackage(CONSTANT_Package_info info, Void p) { - print("#" + info.name_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitString(CONSTANT_String_info info, Void p) { - print("#" + info.string_index); - tab(); - println("// " + stringValue(info)); - return 1; - } - - public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) { - println(stringValue(info)); - return 1; - } - - }; println("Constant pool:"); indent(+1); int width = String.valueOf(constant_pool.size()).length() + 1; @@ -178,321 +64,228 @@ public class ConstantWriter extends BasicWriter { while (cpx < constant_pool.size()) { print(String.format("%" + width + "s", ("#" + cpx))); try { - CPInfo cpInfo = constant_pool.get(cpx); - print(String.format(" = %-18s ", cpTagName(cpInfo))); - cpx += cpInfo.accept(v, null); - } catch (ConstantPool.InvalidIndex ex) { - // should not happen + var cpInfo = constant_pool.entryByIndex(cpx); + print(String.format(" = %-18s ", cpTagName(cpInfo.tag()))); + switch (cpInfo) { + case ClassEntry info -> { + print(() -> "#" + info.name().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case AnnotationConstantValueEntry info -> { + println(() -> stringValue(info)); + } + case MemberRefEntry info -> { + print(() -> "#" + info.owner().index() + ".#" + + info.nameAndType().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case DynamicConstantPoolEntry info -> { + print(() -> "#" + info.bootstrapMethodIndex() + ":#" + + info.nameAndType().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case MethodHandleEntry info -> { + print(() -> info.kind() + ":#" + info.reference().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case MethodTypeEntry info -> { + print(() -> "#" + info.descriptor().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case ModuleEntry info -> { + print(() -> "#" + info.name().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case NameAndTypeEntry info -> { + print(() -> "#" + info.name().index() + ":#" + info.type().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + case PackageEntry info -> { + print(() -> "#" + info.name().index()); + tab(); + println("// " + stringValue(info)); + } + case StringEntry info -> { + print(() -> "#" + info.utf8().index()); + tab(); + println(() -> "// " + stringValue(info)); + } + default -> + throw new IllegalArgumentException("unknown entry: "+ cpInfo); + } + cpx += cpInfo.width(); + } catch (IllegalArgumentException e) { + println(report(e)); + cpx++; } } indent(-1); } protected void write(int cpx) { - ClassFile classFile = classWriter.getClassFile(); if (cpx == 0) { print("#0"); return; } + var classModel = classWriter.getClassModel(); - CPInfo cpInfo; - try { - cpInfo = classFile.constant_pool.get(cpx); - } catch (ConstantPoolException e) { - print("#" + cpx); - return; - } - - int tag = cpInfo.getTag(); - switch (tag) { - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_Fieldref: - // simplify references within this class - CPRefInfo ref = (CPRefInfo) cpInfo; - try { - if (ref.class_index == classFile.this_class) - cpInfo = classFile.constant_pool.get(ref.name_and_type_index); - } catch (ConstantPool.InvalidIndex e) { - // ignore, for now - } + var cpInfo = classModel.constantPool().entryByIndex(cpx); + var tag = cpInfo.tag(); + if (cpInfo instanceof MemberRefEntry ref) { + // simplify references within this class + if (ref.owner().index() == classModel.thisClass().index()) + cpInfo = ref.nameAndType(); } print(tagName(tag) + " " + stringValue(cpInfo)); } - String cpTagName(CPInfo cpInfo) { - String n = cpInfo.getClass().getSimpleName(); - return n.replace("CONSTANT_", "").replace("_info", ""); + String cpTagName(int tag) { + return switch (tag) { + case TAG_UTF8 -> "Utf8"; + case TAG_INTEGER -> "Integer"; + case TAG_FLOAT -> "Float"; + case TAG_LONG -> "Long"; + case TAG_DOUBLE -> "Double"; + case TAG_CLASS -> "Class"; + case TAG_STRING -> "String"; + case TAG_FIELDREF -> "Fieldref"; + case TAG_METHODHANDLE -> "MethodHandle"; + case TAG_METHODTYPE -> "MethodType"; + case TAG_METHODREF -> "Methodref"; + case TAG_INTERFACEMETHODREF -> "InterfaceMethodref"; + case TAG_INVOKEDYNAMIC -> "InvokeDynamic"; + case TAG_CONSTANTDYNAMIC -> "Dynamic"; + case TAG_NAMEANDTYPE -> "NameAndType"; + default -> "Unknown"; + }; } String tagName(int tag) { - switch (tag) { - case CONSTANT_Utf8: - return "Utf8"; - case CONSTANT_Integer: - return "int"; - case CONSTANT_Float: - return "float"; - case CONSTANT_Long: - return "long"; - case CONSTANT_Double: - return "double"; - case CONSTANT_Class: - return "class"; - case CONSTANT_String: - return "String"; - case CONSTANT_Fieldref: - return "Field"; - case CONSTANT_MethodHandle: - return "MethodHandle"; - case CONSTANT_MethodType: - return "MethodType"; - case CONSTANT_Methodref: - return "Method"; - case CONSTANT_InterfaceMethodref: - return "InterfaceMethod"; - case CONSTANT_InvokeDynamic: - return "InvokeDynamic"; - case CONSTANT_Dynamic: - return "Dynamic"; - case CONSTANT_NameAndType: - return "NameAndType"; - default: - return "(unknown tag " + tag + ")"; + return switch (tag) { + case TAG_UTF8 -> "Utf8"; + case TAG_INTEGER -> "int"; + case TAG_FLOAT -> "float"; + case TAG_LONG -> "long"; + case TAG_DOUBLE -> "double"; + case TAG_CLASS -> "class"; + case TAG_STRING -> "String"; + case TAG_FIELDREF -> "Field"; + case TAG_METHODHANDLE -> "MethodHandle"; + case TAG_METHODTYPE -> "MethodType"; + case TAG_METHODREF -> "Method"; + case TAG_INTERFACEMETHODREF -> "InterfaceMethod"; + case TAG_INVOKEDYNAMIC -> "InvokeDynamic"; + case TAG_CONSTANTDYNAMIC -> "Dynamic"; + case TAG_NAMEANDTYPE -> "NameAndType"; + default -> "(unknown tag " + tag + ")"; + }; + } + + String booleanValue(PoolEntry info) { + if (info instanceof IntegerEntry ie) { + switch (ie.intValue()) { + case 0: return "false"; + case 1: return "true"; + } } + return "#" + info.index(); } String booleanValue(int constant_pool_index) { - ClassFile classFile = classWriter.getClassFile(); - try { - CPInfo info = classFile.constant_pool.get(constant_pool_index); - if (info instanceof CONSTANT_Integer_info) { - int value = ((CONSTANT_Integer_info) info).value; - switch (value) { - case 0: return "false"; - case 1: return "true"; - } - } - return "#" + constant_pool_index; - } catch (ConstantPool.InvalidIndex e) { - return report(e); + var info = classWriter.getClassModel().constantPool() + .entryByIndex(constant_pool_index); + if (info instanceof IntegerEntry ie) { + switch (ie.intValue()) { + case 0: return "false"; + case 1: return "true"; + } + } + return "#" + constant_pool_index; + } + + String charValue(PoolEntry info) { + if (info instanceof IntegerEntry ie) { + int value = ie.intValue(); + return String.valueOf((char) value); + } else { + return "#" + info.index(); } } String charValue(int constant_pool_index) { - ClassFile classFile = classWriter.getClassFile(); - try { - CPInfo info = classFile.constant_pool.get(constant_pool_index); - if (info instanceof CONSTANT_Integer_info) { - int value = ((CONSTANT_Integer_info) info).value; - return String.valueOf((char) value); - } else { - return "#" + constant_pool_index; - } - } catch (ConstantPool.InvalidIndex e) { - return report(e); + var info = classWriter.getClassModel().constantPool() + .entryByIndex(constant_pool_index); + if (info instanceof IntegerEntry ie) { + int value = ie.intValue(); + return String.valueOf((char) value); + } else { + return "#" + constant_pool_index; } } String stringValue(int constant_pool_index) { - ClassFile classFile = classWriter.getClassFile(); - try { - return stringValue(classFile.constant_pool.get(constant_pool_index)); - } catch (ConstantPool.InvalidIndex e) { - return report(e); - } + return stringValue(classWriter.getClassModel().constantPool() + .entryByIndex(constant_pool_index)); } - String stringValue(CPInfo cpInfo) { - return stringValueVisitor.visit(cpInfo); - } - - StringValueVisitor stringValueVisitor = new StringValueVisitor(); - - private class StringValueVisitor implements ConstantPool.Visitor { - public String visit(CPInfo info) { - return info.accept(this, null); - } - - public String visitClass(CONSTANT_Class_info info, Void p) { - return getCheckedName(info); - } - - String getCheckedName(CONSTANT_Class_info info) { - try { - return checkName(info.getName()); - } catch (ConstantPoolException e) { - return report(e); + String stringValue(PoolEntry cpInfo) { + return switch (cpInfo) { + case ClassEntry info -> checkName(info.asInternalName()); + case DoubleEntry info -> info.doubleValue() + "d"; + case MemberRefEntry info -> checkName(info.owner().asInternalName()) + + '.' + stringValue(info.nameAndType()); + case FloatEntry info -> info.floatValue()+ "f"; + case IntegerEntry info -> String.valueOf(info.intValue()); + case DynamicConstantPoolEntry info -> "#" + info.bootstrapMethodIndex() + + ":" + stringValue(info.nameAndType()); + case LongEntry info -> info.longValue()+ "l"; + case ModuleEntry info -> checkName(info.name().stringValue()); + case NameAndTypeEntry info -> checkName(info.name().stringValue()) + + ':' + info.type().stringValue(); + case PackageEntry info -> checkName(info.name().stringValue()); + case MethodHandleEntry info -> { + String kind = switch (info.asSymbol().kind()) { + case STATIC, INTERFACE_STATIC -> "REF_invokeStatic"; + case VIRTUAL -> "REF_invokeVirtual"; + case INTERFACE_VIRTUAL -> "REF_invokeInterface"; + case SPECIAL, INTERFACE_SPECIAL -> "REF_invokeSpecial"; + case CONSTRUCTOR -> "REF_newInvokeSpecial"; + case GETTER -> "REF_getField"; + case SETTER -> "REF_putField"; + case STATIC_GETTER -> "REF_getStatic"; + case STATIC_SETTER -> "REF_putStatic"; + }; + yield kind + " " + stringValue(info.reference()); } - } - - public String visitDouble(CONSTANT_Double_info info, Void p) { - return info.value + "d"; - } - - public String visitFieldref(CONSTANT_Fieldref_info info, Void p) { - return visitRef(info, p); - } - - public String visitFloat(CONSTANT_Float_info info, Void p) { - return info.value + "f"; - } - - public String visitInteger(CONSTANT_Integer_info info, Void p) { - return String.valueOf(info.value); - } - - public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { - return visitRef(info, p); - } - - public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) { - try { - String callee = stringValue(info.getNameAndTypeInfo()); - return "#" + info.bootstrap_method_attr_index + ":" + callee; - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitDynamicConstant(CONSTANT_Dynamic_info info, Void p) { - try { - String callee = stringValue(info.getNameAndTypeInfo()); - return "#" + info.bootstrap_method_attr_index + ":" + callee; - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitLong(CONSTANT_Long_info info, Void p) { - return info.value + "l"; - } - - public String visitModule(CONSTANT_Module_info info, Void p) { - try { - return checkName(info.getName()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) { - return getCheckedName(info) + ":" + getType(info); - } - - String getCheckedName(CONSTANT_NameAndType_info info) { - try { - return checkName(info.getName()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitPackage(CONSTANT_Package_info info, Void p) { - try { - return checkName(info.getName()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - String getType(CONSTANT_NameAndType_info info) { - try { - return info.getType(); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) { - try { - return info.reference_kind + " " + stringValue(info.getCPRefInfo()); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitMethodType(CONSTANT_MethodType_info info, Void p) { - try { - return info.getType(); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitMethodref(CONSTANT_Methodref_info info, Void p) { - return visitRef(info, p); - } - - public String visitString(CONSTANT_String_info info, Void p) { - try { - ClassFile classFile = classWriter.getClassFile(); - int string_index = info.string_index; - return stringValue(classFile.constant_pool.getUTF8Info(string_index)); - } catch (ConstantPoolException e) { - return report(e); - } - } - - public String visitUtf8(CONSTANT_Utf8_info info, Void p) { - String s = info.value; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\t': - sb.append('\\').append('t'); - break; - case '\n': - sb.append('\\').append('n'); - break; - case '\r': - sb.append('\\').append('r'); - break; - case '\b': - sb.append('\\').append('b'); - break; - case '\f': - sb.append('\\').append('f'); - break; - case '\"': - sb.append('\\').append('\"'); - break; - case '\'': - sb.append('\\').append('\''); - break; - case '\\': - sb.append('\\').append('\\'); - break; - default: - if (Character.isISOControl(c)) { - sb.append(String.format("\\u%04x", (int) c)); - break; - } - sb.append(c); + case MethodTypeEntry info -> info.descriptor().stringValue(); + case StringEntry info -> stringValue(info.utf8()); + case Utf8Entry info -> { + StringBuilder sb = new StringBuilder(); + for (char c : info.stringValue().toCharArray()) { + sb.append(switch (c) { + case '\t' -> "\\t"; + case '\n' -> "\\n"; + case '\r' -> "\\r"; + case '\b' -> "\\b"; + case '\f' -> "\\f"; + case '\"' -> "\\\""; + case '\'' -> "\\\'"; + case '\\' -> "\\\\"; + default -> Character.isISOControl(c) + ? String.format("\\u%04x", (int) c) : c; + }); } + yield sb.toString(); } - return sb.toString(); - } - - String visitRef(CPRefInfo info, Void p) { - String cn = getCheckedClassName(info); - String nat; - try { - nat = stringValue(info.getNameAndTypeInfo()); - } catch (ConstantPoolException e) { - nat = report(e); - } - return cn + "." + nat; - } - - String getCheckedClassName(CPRefInfo info) { - try { - return checkName(info.getClassName()); - } catch (ConstantPoolException e) { - return report(e); - } - } + default -> throw new IllegalArgumentException("unknown " + cpInfo); + }; } /* If name is a valid binary name, return it; otherwise quote it. */ diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/InstructionDetailWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/InstructionDetailWriter.java index 8a828b8f2b3..ad59393694f 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/InstructionDetailWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/InstructionDetailWriter.java @@ -25,7 +25,7 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Instruction; +import jdk.internal.classfile.Instruction; /* @@ -56,6 +56,6 @@ public abstract class InstructionDetailWriter extends BasicWriter { super(context); } - abstract void writeDetails(Instruction instr); - void flush() { } + abstract void writeDetails(int pc, Instruction instr); + void flush(int pc) { } } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java index 638043d5620..134b4b424b7 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java @@ -67,7 +67,10 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; -import com.sun.tools.classfile.*; +import jdk.internal.classfile.ClassModel; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.constantpool.*; +import static jdk.internal.classfile.Classfile.*; /** * "Main" class for javap, normally accessed from the command line @@ -166,7 +169,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { @Override void process(JavapTask task, String opt, String arg) { task.options.accessOptions.add(opt); - task.options.showAccess = AccessFlags.ACC_PUBLIC; + task.options.showAccess = ACC_PUBLIC; } }, @@ -174,7 +177,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { @Override void process(JavapTask task, String opt, String arg) { task.options.accessOptions.add(opt); - task.options.showAccess = AccessFlags.ACC_PROTECTED; + task.options.showAccess = ACC_PROTECTED; } }, @@ -193,7 +196,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { !task.options.accessOptions.contains("-private")) { task.options.accessOptions.add(opt); } - task.options.showAccess = AccessFlags.ACC_PRIVATE; + task.options.showAccess = ACC_PRIVATE; } }, @@ -349,7 +352,6 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { context = new Context(); context.put(Messages.class, this); options = Options.instance(context); - attributeFactory = new Attribute.Factory(); } public JavapTask(Writer out, @@ -633,7 +635,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { } catch (OutOfMemoryError e) { reportError("err.nomem"); result = EXIT_ERROR; - } catch (FatalError e) { + } catch (IllegalArgumentException e) { Object msg = e.getLocalizedMessage(); if (msg == null) { msg = e; @@ -654,7 +656,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { } protected int writeClass(ClassWriter classWriter, String className) - throws IOException, ConstantPoolException { + throws IOException { JavaFileObject fo = open(className); if (fo == null) { reportError("err.class.not.found", className); @@ -663,34 +665,26 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ClassFileInfo cfInfo = read(fo); if (!className.endsWith(".class")) { - if (cfInfo.cf.this_class == 0) { - if (!className.equals("module-info")) { - reportWarning("warn.unexpected.class", fo.getName(), className); - } - } else { - String cfName = cfInfo.cf.getName(); - if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) { - reportWarning("warn.unexpected.class", fo.getName(), className); - } + String cfName = cfInfo.cm.thisClass().asInternalName(); + if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) { + reportWarning("warn.unexpected.class", fo.getName(), className); } } - write(cfInfo); + if (!write(cfInfo)) return EXIT_ERROR; if (options.showInnerClasses) { - ClassFile cf = cfInfo.cf; - Attribute a = cf.getAttribute(Attribute.InnerClasses); - if (a instanceof InnerClasses_attribute) { - InnerClasses_attribute inners = (InnerClasses_attribute) a; + ClassModel cm = cfInfo.cm; + var a = cm.findAttribute(jdk.internal.classfile.Attributes.INNER_CLASSES); + if (a.isPresent()) { + var inners = a.get(); try { int result = EXIT_OK; - for (int i = 0; i < inners.classes.length; i++) { - int outerIndex = inners.classes[i].outer_class_info_index; - ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex); - String outerClassName = outerClassInfo.getName(); - if (outerClassName.equals(cf.getName())) { - int innerIndex = inners.classes[i].inner_class_info_index; - ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex); - String innerClassName = innerClassInfo.getName(); + for (var inner : inners.classes()) { + var outerClassInfo = inner.outerClass(); + String outerClassName = outerClassInfo.map(ClassEntry::asInternalName).orElse(null); + if (cm.thisClass().asInternalName().equals(outerClassName)) { + var innerClassInfo = inner.innerClass(); + String innerClassName = innerClassInfo.asInternalName(); classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", ".")); classWriter.println(); result = writeClass(classWriter, innerClassName); @@ -698,13 +692,10 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { } } return result; - } catch (ConstantPoolException e) { + } catch (IllegalArgumentException e) { reportError("err.bad.innerclasses.attribute", className); return EXIT_ERROR; } - } else if (a != null) { - reportError("err.bad.innerclasses.attribute", className); - return EXIT_ERROR; } } @@ -811,19 +802,19 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { } public static class ClassFileInfo { - ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) { + ClassFileInfo(JavaFileObject fo, ClassModel cm, byte[] digest, int size) { this.fo = fo; - this.cf = cf; + this.cm = cm; this.digest = digest; this.size = size; } public final JavaFileObject fo; - public final ClassFile cf; + public final ClassModel cm; public final byte[] digest; public final int size; } - public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException { + public ClassFileInfo read(JavaFileObject fo) throws IOException { InputStream in = fo.openInputStream(); try { SizeInputStream sizeIn = null; @@ -836,17 +827,16 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { in = new DigestInputStream(in, md); in = sizeIn = new SizeInputStream(in); } - - ClassFile cf = ClassFile.read(in, attributeFactory); + ClassModel cm = Classfile.of().parse(in.readAllBytes()); byte[] digest = (md == null) ? null : md.digest(); int size = (sizeIn == null) ? -1 : sizeIn.size(); - return new ClassFileInfo(fo, cf, digest, size); + return new ClassFileInfo(fo, cm, digest, size); } finally { in.close(); } } - public void write(ClassFileInfo info) { + public boolean write(ClassFileInfo info) { ClassWriter classWriter = ClassWriter.instance(context); if (options.sysInfo || options.verbose) { classWriter.setFile(info.fo.toUri()); @@ -855,56 +845,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { classWriter.setFileSize(info.size); } - classWriter.write(info.cf); - } - - protected void setClassFile(ClassFile classFile) { - ClassWriter classWriter = ClassWriter.instance(context); - classWriter.setClassFile(classFile); - } - - protected void setMethod(Method enclosingMethod) { - ClassWriter classWriter = ClassWriter.instance(context); - classWriter.setMethod(enclosingMethod); - } - - protected void write(Attribute value) { - AttributeWriter attrWriter = AttributeWriter.instance(context); - ClassWriter classWriter = ClassWriter.instance(context); - ClassFile cf = classWriter.getClassFile(); - attrWriter.write(cf, value, cf.constant_pool); - } - - protected void write(Attributes attrs) { - AttributeWriter attrWriter = AttributeWriter.instance(context); - ClassWriter classWriter = ClassWriter.instance(context); - ClassFile cf = classWriter.getClassFile(); - attrWriter.write(cf, attrs, cf.constant_pool); - } - - protected void write(ConstantPool constant_pool) { - ConstantWriter constantWriter = ConstantWriter.instance(context); - constantWriter.writeConstantPool(constant_pool); - } - - protected void write(ConstantPool constant_pool, int value) { - ConstantWriter constantWriter = ConstantWriter.instance(context); - constantWriter.write(value); - } - - protected void write(ConstantPool.CPInfo value) { - ConstantWriter constantWriter = ConstantWriter.instance(context); - constantWriter.println(value); - } - - protected void write(Field value) { - ClassWriter classWriter = ClassWriter.instance(context); - classWriter.writeField(value); - } - - protected void write(Method value) { - ClassWriter classWriter = ClassWriter.instance(context); - classWriter.writeMethod(value); + return classWriter.write(info.cm); } private JavaFileManager getDefaultFileManager(final DiagnosticListener dl, PrintWriter log) { @@ -944,7 +885,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { if (result == null) result = l; else - throw new IOException("multiple definitions found for " + moduleName); + throw new IOException("multiple definitions found for " + + moduleName); } } if (result != null) @@ -957,7 +899,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { private void showHelp() { printLines(getMessage("main.usage", progname)); for (Option o: recognizedOptions) { - String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_"); // there must always be at least one name + // there must always be at least one name + String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_"); if (name.startsWith("X") || name.equals("fullversion")) continue; printLines(getMessage("main.opt." + name)); @@ -1000,7 +943,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { try { versionRB = ResourceBundle.getBundle(versionRBName); } catch (MissingResourceException e) { - return getMessage("version.resource.missing", System.getProperty("java.version")); + return getMessage("version.resource.missing", + System.getProperty("java.version")); } } try { @@ -1064,7 +1008,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { @Override public String toString() { - return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]"; + return getClass().getName() + "[key=" + key + ",args=" + + Arrays.asList(args) + "]"; } }; @@ -1089,10 +1034,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ResourceBundle b = bundles.get(locale); if (b == null) { try { - b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale); + b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", + locale); bundles.put(locale, b); } catch (MissingResourceException e) { - throw new InternalError("Cannot find javap resource bundle for locale " + locale); + throw new InternalError("Cannot find javap resource bundle for locale " + + locale); } } @@ -1114,7 +1061,6 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { //ResourceBundle bundle; Locale task_locale; Map bundles; - protected Attribute.Factory attributeFactory; private static final String progname = "javap"; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTableWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTableWriter.java index d8438daf971..76141ce039a 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTableWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTableWriter.java @@ -25,19 +25,15 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.LocalVariableTable_attribute; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.CodeModel; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.Signature; +import jdk.internal.classfile.attribute.LocalVariableInfo; /** * Annotate instructions with details about local variables. @@ -47,22 +43,24 @@ import java.util.Map; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class LocalVariableTableWriter extends InstructionDetailWriter { +public class LocalVariableTableWriter extends InstructionDetailWriter { public enum NoteKind { START("start") { - public boolean match(LocalVariableTable_attribute.Entry entry, int pc) { - return (pc == entry.start_pc); + @Override + public boolean match(LocalVariableInfo entry, int pc) { + return (pc == entry.startPc()); } }, END("end") { - public boolean match(LocalVariableTable_attribute.Entry entry, int pc) { - return (pc == entry.start_pc + entry.length); + @Override + public boolean match(LocalVariableInfo entry, int pc) { + return (pc == entry.startPc() + entry.length()); } }; NoteKind(String text) { this.text = text; } - public abstract boolean match(LocalVariableTable_attribute.Entry entry, int pc); + public abstract boolean match(LocalVariableInfo entry, int pc); public final String text; } @@ -79,71 +77,56 @@ public class LocalVariableTableWriter extends InstructionDetailWriter { classWriter = ClassWriter.instance(context); } - public void reset(Code_attribute attr) { + public void reset(CodeModel attr) { codeAttr = attr; pcMap = new HashMap<>(); - LocalVariableTable_attribute lvt = - (LocalVariableTable_attribute) (attr.attributes.get(Attribute.LocalVariableTable)); - if (lvt == null) + var lvt = attr.findAttribute(Attributes.LOCAL_VARIABLE_TABLE); + + if (lvt.isEmpty()) return; - for (int i = 0; i < lvt.local_variable_table.length; i++) { - LocalVariableTable_attribute.Entry entry = lvt.local_variable_table[i]; - put(entry.start_pc, entry); - put(entry.start_pc + entry.length, entry); + for (var entry : lvt.get().localVariables()) { + put(entry.startPc(), entry); + put(entry.startPc() + entry.length(), entry); } } - public void writeDetails(Instruction instr) { - int pc = instr.getPC(); + @Override + public void writeDetails(int pc, Instruction instr) { writeLocalVariables(pc, NoteKind.END); writeLocalVariables(pc, NoteKind.START); } @Override - public void flush() { - int pc = codeAttr.code_length; + public void flush(int pc) { writeLocalVariables(pc, NoteKind.END); } public void writeLocalVariables(int pc, NoteKind kind) { - ConstantPool constant_pool = classWriter.getClassFile().constant_pool; String indent = space(2); // get from Options? - List entries = pcMap.get(pc); + var entries = pcMap.get(pc); if (entries != null) { - for (ListIterator iter = - entries.listIterator(kind == NoteKind.END ? entries.size() : 0); + for (var iter = entries.listIterator(kind == NoteKind.END ? entries.size() : 0); kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { - LocalVariableTable_attribute.Entry entry = - kind == NoteKind.END ? iter.previous() : iter.next(); + var entry = kind == NoteKind.END ? iter.previous() : iter.next(); if (kind.match(entry, pc)) { print(indent); print(kind.text); print(" local "); - print(entry.index); + print(entry.slot()); print(" // "); - Descriptor d = new Descriptor(entry.descriptor_index); - try { - print(d.getFieldType(constant_pool)); - } catch (InvalidDescriptor e) { - print(report(e)); - } catch (ConstantPoolException e) { - print(report(e)); - } + print(classWriter.sigPrinter.print( + Signature.parseFrom(entry.type().stringValue()))); print(" "); - try { - print(constant_pool.getUTF8Value(entry.name_index)); - } catch (ConstantPoolException e) { - print(report(e)); - } + print(entry.name().stringValue()); println(); } } } } - private void put(int pc, LocalVariableTable_attribute.Entry entry) { - List list = pcMap.get(pc); + private void put(int pc, LocalVariableInfo entry) { + var list = pcMap.get(pc); if (list == null) { list = new ArrayList<>(); pcMap.put(pc, list); @@ -153,6 +136,6 @@ public class LocalVariableTableWriter extends InstructionDetailWriter { } private ClassWriter classWriter; - private Code_attribute codeAttr; - private Map> pcMap; + private CodeModel codeAttr; + private Map> pcMap; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java index d1a8c68de72..fce73156c06 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java @@ -25,20 +25,15 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.LocalVariableTypeTable_attribute; -import com.sun.tools.classfile.Signature; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.CodeModel; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.Signature; +import jdk.internal.classfile.attribute.LocalVariableTypeInfo; /** * Annotate instructions with details about local variables. @@ -51,19 +46,21 @@ import java.util.Map; public class LocalVariableTypeTableWriter extends InstructionDetailWriter { public enum NoteKind { START("start") { - public boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc) { - return (pc == entry.start_pc); + @Override + public boolean match(LocalVariableTypeInfo entry, int pc) { + return (pc == entry.startPc()); } }, END("end") { - public boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc) { - return (pc == entry.start_pc + entry.length); + @Override + public boolean match(LocalVariableTypeInfo entry, int pc) { + return (pc == entry.startPc() + entry.length()); } }; NoteKind(String text) { this.text = text; } - public abstract boolean match(LocalVariableTypeTable_attribute.Entry entry, int pc); + public abstract boolean match(LocalVariableTypeInfo entry, int pc); public final String text; } @@ -80,71 +77,60 @@ public class LocalVariableTypeTableWriter extends InstructionDetailWriter { classWriter = ClassWriter.instance(context); } - public void reset(Code_attribute attr) { + public void reset(CodeModel attr) { codeAttr = attr; pcMap = new HashMap<>(); - LocalVariableTypeTable_attribute lvt = - (LocalVariableTypeTable_attribute) (attr.attributes.get(Attribute.LocalVariableTypeTable)); - if (lvt == null) + var lvt = attr.findAttribute(Attributes.LOCAL_VARIABLE_TYPE_TABLE); + + if (lvt.isEmpty()) return; - for (int i = 0; i < lvt.local_variable_table.length; i++) { - LocalVariableTypeTable_attribute.Entry entry = lvt.local_variable_table[i]; - put(entry.start_pc, entry); - put(entry.start_pc + entry.length, entry); + for (var entry : lvt.get().localVariableTypes()) { + put(entry.startPc(), entry); + put(entry.startPc() + entry.length(), entry); } } - public void writeDetails(Instruction instr) { - int pc = instr.getPC(); + @Override + public void writeDetails(int pc, Instruction instr) { writeLocalVariables(pc, NoteKind.END); writeLocalVariables(pc, NoteKind.START); } @Override - public void flush() { - int pc = codeAttr.code_length; + public void flush(int pc) { writeLocalVariables(pc, NoteKind.END); } public void writeLocalVariables(int pc, NoteKind kind) { - ConstantPool constant_pool = classWriter.getClassFile().constant_pool; String indent = space(2); // get from Options? - List entries = pcMap.get(pc); + var entries = pcMap.get(pc); if (entries != null) { - for (ListIterator iter = - entries.listIterator(kind == NoteKind.END ? entries.size() : 0); + for (var iter = entries.listIterator(kind == NoteKind.END ? entries.size() : 0); kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { - LocalVariableTypeTable_attribute.Entry entry = - kind == NoteKind.END ? iter.previous() : iter.next(); + var entry = kind == NoteKind.END ? iter.previous() : iter.next(); if (kind.match(entry, pc)) { print(indent); print(kind.text); print(" generic local "); - print(entry.index); + print(entry.slot()); print(" // "); - Descriptor d = new Signature(entry.signature_index); try { - print(d.getFieldType(constant_pool).replace("/", ".")); - } catch (InvalidDescriptor e) { - print(report(e)); - } catch (ConstantPoolException e) { + print(classWriter.sigPrinter.print(Signature.parseFrom( + entry.signature().stringValue())).replace("/", ".")); + } catch (Exception e) { print(report(e)); } print(" "); - try { - print(constant_pool.getUTF8Value(entry.name_index)); - } catch (ConstantPoolException e) { - print(report(e)); - } + print(entry.name().stringValue()); println(); } } } } - private void put(int pc, LocalVariableTypeTable_attribute.Entry entry) { - List list = pcMap.get(pc); + private void put(int pc, LocalVariableTypeInfo entry) { + var list = pcMap.get(pc); if (list == null) { list = new ArrayList<>(); pcMap.put(pc, list); @@ -154,6 +140,6 @@ public class LocalVariableTypeTableWriter extends InstructionDetailWriter { } private ClassWriter classWriter; - private Code_attribute codeAttr; - private Map> pcMap; + private CodeModel codeAttr; + private Map> pcMap; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java index 3a31155d688..2beefb66dbd 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java @@ -29,7 +29,7 @@ import java.util.EnumSet; import java.util.HashSet; import java.util.Set; -import com.sun.tools.classfile.AccessFlags; +import static jdk.internal.classfile.Classfile.*; /* * Provides access to javap's options, set via the command line @@ -54,16 +54,16 @@ public class Options { /** * Checks access of class, field or method. */ - public boolean checkAccess(AccessFlags flags){ + public boolean checkAccess(int flags){ - boolean isPublic = flags.is(AccessFlags.ACC_PUBLIC); - boolean isProtected = flags.is(AccessFlags.ACC_PROTECTED); - boolean isPrivate = flags.is(AccessFlags.ACC_PRIVATE); + boolean isPublic = (flags & ACC_PUBLIC) != 0; + boolean isProtected = (flags & ACC_PROTECTED) != 0; + boolean isPrivate = (flags & ACC_PRIVATE) != 0; boolean isPackage = !(isPublic || isProtected || isPrivate); - if ((showAccess == AccessFlags.ACC_PUBLIC) && (isProtected || isPrivate || isPackage)) + if ((showAccess == ACC_PUBLIC) && (isProtected || isPrivate || isPackage)) return false; - else if ((showAccess == AccessFlags.ACC_PROTECTED) && (isPrivate || isPackage)) + else if ((showAccess == ACC_PROTECTED) && (isPrivate || isPackage)) return false; else if ((showAccess == 0) && (isPrivate)) return false; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/SourceWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/SourceWriter.java index da31777f3b7..775ab6f1ba8 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/SourceWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/SourceWriter.java @@ -30,7 +30,6 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; @@ -40,13 +39,10 @@ import javax.tools.JavaFileManager.Location; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.ClassFile; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.LineNumberTable_attribute; -import com.sun.tools.classfile.SourceFile_attribute; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.ClassModel; +import jdk.internal.classfile.CodeModel; +import jdk.internal.classfile.Instruction; /** @@ -74,14 +70,15 @@ public class SourceWriter extends InstructionDetailWriter { this.fileManager = fileManager; } - public void reset(ClassFile cf, Code_attribute attr) { - setSource(cf); + public void reset(CodeModel attr) { + setSource(attr.parent().get().parent().get()); setLineMap(attr); } - public void writeDetails(Instruction instr) { + @Override + public void writeDetails(int pc, Instruction instr) { String indent = space(40); // could get from Options? - Set lines = lineMap.get(instr.getPC()); + var lines = lineMap.get(pc); if (lines != null) { for (int line: lines) { print(indent); @@ -105,37 +102,34 @@ public class SourceWriter extends InstructionDetailWriter { return (sourceLines.length > 0); } - private void setLineMap(Code_attribute attr) { + private void setLineMap(CodeModel attr) { SortedMap> map = new TreeMap<>(); SortedSet allLines = new TreeSet<>(); - for (Attribute a: attr.attributes) { - if (a instanceof LineNumberTable_attribute) { - LineNumberTable_attribute t = (LineNumberTable_attribute) a; - for (LineNumberTable_attribute.Entry e: t.line_number_table) { - int start_pc = e.start_pc; - int line = e.line_number; - SortedSet pcLines = map.get(start_pc); - if (pcLines == null) { - pcLines = new TreeSet<>(); - map.put(start_pc, pcLines); - } - pcLines.add(line); - allLines.add(line); + for (var t : attr.findAttributes(Attributes.LINE_NUMBER_TABLE)) { + for (var e: t.lineNumbers()) { + int start_pc = e.startPc(); + int line = e.lineNumber(); + SortedSet pcLines = map.get(start_pc); + if (pcLines == null) { + pcLines = new TreeSet<>(); + map.put(start_pc, pcLines); } + pcLines.add(line); + allLines.add(line); } } lineMap = map; lineList = new ArrayList<>(allLines); } - private void setSource(ClassFile cf) { + private void setSource(ClassModel cf) { if (cf != classFile) { classFile = cf; sourceLines = splitLines(readSource(cf)); } } - private String readSource(ClassFile cf) { + private String readSource(ClassModel cf) { if (fileManager == null) return null; @@ -150,14 +144,13 @@ public class SourceWriter extends InstructionDetailWriter { // additional classes to determine the outmost class from any // InnerClasses and EnclosingMethod attributes. try { - String className = cf.getName(); - SourceFile_attribute sf = - (SourceFile_attribute) cf.attributes.get(Attribute.SourceFile); - if (sf == null) { + String className = cf.thisClass().asInternalName(); + var sf = cf.findAttribute(Attributes.SOURCE_FILE); + if (sf.isEmpty()) { report(messages.getMessage("err.no.SourceFile.attribute")); return null; } - String sourceFile = sf.getSourceFile(cf.constant_pool); + String sourceFile = sf.get().sourceFile().stringValue(); String fileBase = sourceFile.endsWith(".java") ? sourceFile.substring(0, sourceFile.length() - 5) : sourceFile; int sep = className.lastIndexOf("/"); @@ -172,9 +165,6 @@ public class SourceWriter extends InstructionDetailWriter { return null; } return fo.getCharContent(true).toString(); - } catch (ConstantPoolException e) { - report(e); - return null; } catch (IOException e) { report(e.getLocalizedMessage()); return null; @@ -205,7 +195,7 @@ public class SourceWriter extends InstructionDetailWriter { } private JavaFileManager fileManager; - private ClassFile classFile; + private ClassModel classFile; private SortedMap> lineMap; private List lineList; private String[] sourceLines; diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java index 872521e176c..5c66deab634 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/StackMapWriter.java @@ -25,23 +25,16 @@ package com.sun.tools.javap; -import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.Classfile; -import com.sun.tools.classfile.AccessFlags; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ConstantPool; -import com.sun.tools.classfile.ConstantPoolException; -import com.sun.tools.classfile.Descriptor; -import com.sun.tools.classfile.Descriptor.InvalidDescriptor; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.StackMapTable_attribute; -import com.sun.tools.classfile.StackMapTable_attribute.*; - -import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.attribute.CodeAttribute; +import jdk.internal.classfile.attribute.StackMapFrameInfo; +import jdk.internal.classfile.attribute.StackMapTableAttribute; /** * Annotate instructions with stack map. @@ -62,228 +55,108 @@ public class StackMapWriter extends InstructionDetailWriter { protected StackMapWriter(Context context) { super(context); context.put(StackMapWriter.class, this); - classWriter = ClassWriter.instance(context); } - public void reset(Code_attribute attr) { - setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable)); + public void reset(CodeAttribute code) { + setStackMap(code); } - void setStackMap(StackMapTable_attribute attr) { + void setStackMap(CodeAttribute code) { + StackMapTableAttribute attr = code.findAttribute(Attributes.STACK_MAP_TABLE) + .orElse(null); if (attr == null) { map = null; return; } - - Method m = classWriter.getMethod(); - Descriptor d = m.descriptor; - String[] args; - try { - ConstantPool cp = classWriter.getClassFile().constant_pool; - String argString = d.getParameterTypes(cp); - args = argString.substring(1, argString.length() - 1).split("[, ]+"); - } catch (ConstantPoolException | InvalidDescriptor e) { - return; - } - boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC); - - verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length]; - if (!isStatic) - initialLocals[0] = new CustomVerificationTypeInfo("this"); - for (int i = 0; i < args.length; i++) { - initialLocals[(isStatic ? 0 : 1) + i] = - new CustomVerificationTypeInfo(args[i].replace(".", "/")); + var m = code.parent().get(); + if ((m.flags().flagsMask() & Classfile.ACC_STATIC) == 0) { + thisClassName = m.parent().get().thisClass().asInternalName(); + } else { + thisClassName = null; } map = new HashMap<>(); - StackMapBuilder builder = new StackMapBuilder(); - - // using -1 as the pc for the initial frame effectively compensates for - // the difference in behavior for the first stack map frame (where the - // pc offset is just offset_delta) compared to subsequent frames (where - // the pc offset is always offset_delta+1). - int pc = -1; - - map.put(pc, new StackMap(initialLocals, empty)); - - for (int i = 0; i < attr.entries.length; i++) - pc = attr.entries[i].accept(builder, pc); + this.code = code; + for (var fr : attr.entries()) + map.put(code.labelToBci(fr.target()), fr); } public void writeInitialDetails() { writeDetails(-1); } - public void writeDetails(Instruction instr) { - writeDetails(instr.getPC()); + @Override + public void writeDetails(int pc, Instruction instr) { + writeDetails(pc); } private void writeDetails(int pc) { if (map == null) return; - StackMap m = map.get(pc); + var m = map.get(pc); if (m != null) { - print("StackMap locals: ", m.locals); - print("StackMap stack: ", m.stack); + print("StackMap locals: ", m.locals(), true); + print("StackMap stack: ", m.stack(), false); } } - void print(String label, verification_type_info[] entries) { + void print(String label, List entries, + boolean firstThis) { print(label); - for (int i = 0; i < entries.length; i++) { + for (var e : entries) { print(" "); - print(entries[i]); + print(e, firstThis); + firstThis = false; } println(); } - void print(verification_type_info entry) { + void print(StackMapFrameInfo.VerificationTypeInfo entry, boolean firstThis) { if (entry == null) { print("ERROR"); return; } - switch (entry.tag) { - case -1: - print(((CustomVerificationTypeInfo) entry).text); - break; + switch (entry) { + case StackMapFrameInfo.SimpleVerificationTypeInfo s -> { + switch (s) { + case ITEM_TOP -> + print("top"); - case ITEM_Top: - print("top"); - break; + case ITEM_INTEGER -> + print("int"); - case ITEM_Integer: - print("int"); - break; + case ITEM_FLOAT -> + print("float"); - case ITEM_Float: - print("float"); - break; + case ITEM_LONG -> + print("long"); - case ITEM_Long: - print("long"); - break; + case ITEM_DOUBLE -> + print("double"); - case ITEM_Double: - print("double"); - break; + case ITEM_NULL -> + print("null"); - case ITEM_Null: - print("null"); - break; - - case ITEM_UninitializedThis: - print("uninit_this"); - break; - - case ITEM_Object: - try { - ConstantPool cp = classWriter.getClassFile().constant_pool; - ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index); - print(cp.getUTF8Value(class_info.name_index)); - } catch (ConstantPoolException e) { - print("??"); + case ITEM_UNINITIALIZED_THIS -> + print("uninit_this"); } - break; + } - case ITEM_Uninitialized: - print(((Uninitialized_variable_info) entry).offset); - break; + case StackMapFrameInfo.ObjectVerificationTypeInfo o -> { + String cln = o.className().asInternalName(); + print(firstThis && cln.equals(thisClassName) ? "this" : cln); + } + + case StackMapFrameInfo.UninitializedVerificationTypeInfo u -> + print(code.labelToBci(u.newTarget())); } } - private Map map; - private ClassWriter classWriter; - - class StackMapBuilder - implements StackMapTable_attribute.stack_map_frame.Visitor { - - public Integer visit_same_frame(same_frame frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap m = map.get(pc); - assert (m != null); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap prev = map.get(pc); - assert (prev != null); - StackMap m = new StackMap(prev.locals, frame.stack); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap prev = map.get(pc); - assert (prev != null); - StackMap m = new StackMap(prev.locals, frame.stack); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_chop_frame(chop_frame frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap prev = map.get(pc); - assert (prev != null); - int k = 251 - frame.frame_type; - verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k); - StackMap m = new StackMap(new_locals, empty); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta(); - StackMap m = map.get(pc); - assert (m != null); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_append_frame(append_frame frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap prev = map.get(pc); - assert (prev != null); - verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length]; - System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length); - System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length); - StackMap m = new StackMap(new_locals, empty); - map.put(new_pc, m); - return new_pc; - } - - public Integer visit_full_frame(full_frame frame, Integer pc) { - int new_pc = pc + frame.getOffsetDelta() + 1; - StackMap m = new StackMap(frame.locals, frame.stack); - map.put(new_pc, m); - return new_pc; - } - - } - - static class StackMap { - StackMap(verification_type_info[] locals, verification_type_info[] stack) { - this.locals = locals; - this.stack = stack; - } - - private final verification_type_info[] locals; - private final verification_type_info[] stack; - } - - static class CustomVerificationTypeInfo extends verification_type_info { - public CustomVerificationTypeInfo(String text) { - super(-1); - this.text = text; - } - private String text; - } - - private final verification_type_info[] empty = { }; + private Map map; + private String thisClassName; + private CodeAttribute code; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/TryBlockWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/TryBlockWriter.java index 6cbf363b578..05e127a3f82 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/TryBlockWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/TryBlockWriter.java @@ -25,14 +25,13 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.Code_attribute.Exception_data; -import com.sun.tools.classfile.Instruction; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.instruction.ExceptionCatch; +import jdk.internal.classfile.attribute.CodeAttribute; /** * Annotate instructions with details about try blocks. @@ -45,24 +44,24 @@ import java.util.Map; public class TryBlockWriter extends InstructionDetailWriter { public enum NoteKind { START("try") { - public boolean match(Exception_data entry, int pc) { - return (pc == entry.start_pc); + public boolean match(ExceptionCatch entry, int pc, CodeAttribute lr) { + return (pc == lr.labelToBci(entry.tryStart())); } }, END("end try") { - public boolean match(Exception_data entry, int pc) { - return (pc == entry.end_pc); + public boolean match(ExceptionCatch entry, int pc, CodeAttribute lr) { + return (pc == lr.labelToBci(entry.tryEnd())); } }, HANDLER("catch") { - public boolean match(Exception_data entry, int pc) { - return (pc == entry.handler_pc); + public boolean match(ExceptionCatch entry, int pc, CodeAttribute lr) { + return (pc == lr.labelToBci(entry.handler())); } }; NoteKind(String text) { this.text = text; } - public abstract boolean match(Exception_data entry, int pc); + public abstract boolean match(ExceptionCatch entry, int pc, CodeAttribute lr); public final String text; } @@ -79,46 +78,49 @@ public class TryBlockWriter extends InstructionDetailWriter { constantWriter = ConstantWriter.instance(context); } - public void reset(Code_attribute attr) { + public void reset(CodeAttribute attr) { indexMap = new HashMap<>(); pcMap = new HashMap<>(); - for (int i = 0; i < attr.exception_table.length; i++) { - Exception_data entry = attr.exception_table[i]; + lr = attr; + var excs = attr.exceptionHandlers(); + for (int i = 0; i < excs.size(); i++) { + var entry = excs.get(i); indexMap.put(entry, i); - put(entry.start_pc, entry); - put(entry.end_pc, entry); - put(entry.handler_pc, entry); + put(lr.labelToBci(entry.tryStart()), entry); + put(lr.labelToBci(entry.tryEnd()), entry); + put(lr.labelToBci(entry.handler()), entry); } } - public void writeDetails(Instruction instr) { - writeTrys(instr, NoteKind.END); - writeTrys(instr, NoteKind.START); - writeTrys(instr, NoteKind.HANDLER); + @Override + public void writeDetails(int pc, Instruction instr) { + writeTrys(pc, instr, NoteKind.END); + writeTrys(pc, instr, NoteKind.START); + writeTrys(pc, instr, NoteKind.HANDLER); } - public void writeTrys(Instruction instr, NoteKind kind) { + public void writeTrys(int pc, Instruction instr, NoteKind kind) { String indent = space(2); // get from Options? - int pc = instr.getPC(); - List entries = pcMap.get(pc); + var entries = pcMap.get(pc); if (entries != null) { - for (ListIterator iter = + for (var iter = entries.listIterator(kind == NoteKind.END ? entries.size() : 0); kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) { - Exception_data entry = + var entry = kind == NoteKind.END ? iter.previous() : iter.next(); - if (kind.match(entry, pc)) { + if (kind.match(entry, pc, lr)) { print(indent); print(kind.text); print("["); print(indexMap.get(entry)); print("] "); - if (entry.catch_type == 0) + var ct = entry.catchType(); + if (ct.isEmpty()) print("finally"); else { - print("#" + entry.catch_type); + print("#" + ct.get().index()); print(" // "); - constantWriter.write(entry.catch_type); + constantWriter.write(ct.get().index()); } println(); } @@ -126,8 +128,8 @@ public class TryBlockWriter extends InstructionDetailWriter { } } - private void put(int pc, Exception_data entry) { - List list = pcMap.get(pc); + private void put(int pc, ExceptionCatch entry) { + var list = pcMap.get(pc); if (list == null) { list = new ArrayList<>(); pcMap.put(pc, list); @@ -136,7 +138,8 @@ public class TryBlockWriter extends InstructionDetailWriter { list.add(entry); } - private Map> pcMap; - private Map indexMap; + private Map> pcMap; + private Map indexMap; private ConstantWriter constantWriter; + private CodeAttribute lr; } diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java b/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java index 180c995557e..95222c6de3f 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java @@ -25,20 +25,17 @@ package com.sun.tools.javap; -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.TypeAnnotation; -import com.sun.tools.classfile.TypeAnnotation.Position; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; -import com.sun.tools.javac.util.StringUtils; +import java.util.Optional; +import jdk.internal.classfile.Attributes; +import jdk.internal.classfile.Instruction; +import jdk.internal.classfile.MethodModel; +import jdk.internal.classfile.TypeAnnotation; +import jdk.internal.classfile.attribute.CodeAttribute; /** * Annotate instructions with details about type annotations. @@ -74,28 +71,37 @@ public class TypeAnnotationWriter extends InstructionDetailWriter { classWriter = ClassWriter.instance(context); } - public void reset(Code_attribute attr) { - Method m = classWriter.getMethod(); + public void reset(CodeAttribute attr) { + MethodModel m = attr.parent().get(); pcMap = new HashMap<>(); - check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations)); - check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations)); + codeAttribute = attr; + check(NoteKind.VISIBLE, + m.findAttribute(Attributes.RUNTIME_VISIBLE_TYPE_ANNOTATIONS) + .map(a -> a.annotations())); + check(NoteKind.INVISIBLE, + m.findAttribute(Attributes.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) + .map(a -> a.annotations())); } - private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) { - if (attr == null) + private void check(NoteKind kind, Optional> annos) { + if (annos.isEmpty()) return; - for (TypeAnnotation anno: attr.annotations) { - Position p = anno.position; - Note note = null; - if (p.offset != -1) - addNote(p.offset, note = new Note(kind, anno)); - if (p.lvarOffset != null) { - for (int i = 0; i < p.lvarOffset.length; i++) { - if (note == null) - note = new Note(kind, anno); - addNote(p.lvarOffset[i], note); + for (TypeAnnotation anno: annos.get()) { + switch (anno.targetInfo()) { + case TypeAnnotation.LocalVarTarget p -> { + Note note = null; + for (var lvar : p.table()) { + if (note == null) + note = new Note(kind, anno); + addNote(codeAttribute.labelToBci(lvar.startLabel()), note); + } } + case TypeAnnotation.OffsetTarget p -> + addNote(codeAttribute.labelToBci(p.target()), new Note(kind, anno)); + case TypeAnnotation.TypeArgumentTarget p -> + addNote(codeAttribute.labelToBci(p.target()), new Note(kind, anno)); + default -> {} } } } @@ -108,17 +114,16 @@ public class TypeAnnotationWriter extends InstructionDetailWriter { } @Override - void writeDetails(Instruction instr) { + void writeDetails(int pc, Instruction instr) { String indent = space(2); // get from Options? - int pc = instr.getPC(); List notes = pcMap.get(pc); if (notes != null) { for (Note n: notes) { print(indent); print("@"); - annotationWriter.write(n.anno, false, true); + annotationWriter.write(n.anno, false, true, codeAttribute); print(", "); - println(StringUtils.toLowerCase(n.kind.toString())); + println(n.kind.toString().toLowerCase(Locale.US)); } } } @@ -126,4 +131,5 @@ public class TypeAnnotationWriter extends InstructionDetailWriter { private AnnotationWriter annotationWriter; private ClassWriter classWriter; private Map> pcMap; + private CodeAttribute codeAttribute; } diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index ce78e592180..4d53879d642 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -130,6 +130,7 @@ serviceability/sa/ClhsdbPmap.java#core 8267433 macosx-x64 serviceability/sa/ClhsdbPstack.java#core 8267433 macosx-x64 serviceability/sa/TestJmapCore.java 8267433 macosx-x64 serviceability/sa/TestJmapCoreMetaspace.java 8267433 macosx-x64 +serviceability/sa/ClhsdbDumpclass.java 8316342 generic-all serviceability/attach/ConcAttachTest.java 8290043 linux-all diff --git a/test/langtools/tools/javap/8260403/T8260403.java b/test/langtools/tools/javap/8260403/T8260403.java index be13ea79572..84f7dcde602 100644 --- a/test/langtools/tools/javap/8260403/T8260403.java +++ b/test/langtools/tools/javap/8260403/T8260403.java @@ -30,13 +30,21 @@ * @modules jdk.jdeps/com.sun.tools.javap */ import java.io.PrintWriter; +import java.io.StringWriter; public class T8260403 { public static void main(String args[]) throws Exception { - if (com.sun.tools.javap.Main.run(new String[]{"-c", System.getProperty("test.classes") + "/InvalidSignature.class"}, - new PrintWriter(System.out)) != 0) { - throw new AssertionError(); - } + var sw = new StringWriter(); + int res = com.sun.tools.javap.Main.run( + new String[]{"-c", System.getProperty("test.classes") + "/InvalidSignature.class"}, + new PrintWriter(sw)); + System.out.println(sw); + if (res == 0) + throw new AssertionError("Failure exit code expected"); + if (sw.toString().contains("Fatal error")) + throw new AssertionError("Unguarded fatal error"); + if (sw.toString().contains("error while reading constant pool")) + throw new AssertionError("Unguarded constant pool error"); } } diff --git a/test/langtools/tools/javap/T6866657.java b/test/langtools/tools/javap/T6866657.java index 4273b03fb72..c935d4747f8 100644 --- a/test/langtools/tools/javap/T6866657.java +++ b/test/langtools/tools/javap/T6866657.java @@ -60,7 +60,9 @@ public class T6866657 JavapTask t = new JavapTask(log, fileManager, null); t.handleOptions(new String[] { "-sysinfo", className }); JavapTask.ClassFileInfo cfInfo = t.read(fo); - expectEqual(cfInfo.cf.byteLength(), cfInfo.size); + try (var in = fo.openInputStream()) { + expectEqual(in.readAllBytes().length, cfInfo.size); + } } } catch (Exception e) { e.printStackTrace(); diff --git a/test/langtools/tools/javap/T7186925.java b/test/langtools/tools/javap/T7186925.java index 8309ec0be26..2d4553526b1 100644 --- a/test/langtools/tools/javap/T7186925.java +++ b/test/langtools/tools/javap/T7186925.java @@ -56,7 +56,9 @@ public class T7186925 JavapTask t = new JavapTask(null, fileManager, null); t.handleOptions(new String[] { "-sysinfo", className }); JavapTask.ClassFileInfo cfInfo = t.read(fo); - expectEqual(cfInfo.cf.byteLength(), cfInfo.size); + try (var in = fo.openInputStream()) { + expectEqual(in.readAllBytes().length, cfInfo.size); + } } } catch (NullPointerException ee) { ee.printStackTrace(); diff --git a/test/langtools/tools/javap/malformed/Malformed.jcod b/test/langtools/tools/javap/malformed/Malformed.jcod new file mode 100644 index 00000000000..df1baa6c80d --- /dev/null +++ b/test/langtools/tools/javap/malformed/Malformed.jcod @@ -0,0 +1,54 @@ +class Malformed { + 0xCAFEBABE; + 0; // minor version + 0; // version + [] { // Constant Pool + ; // first element is empty + Utf8 "Code"; // #1 + Method #0 #0; // #2 + class #0; // #3 + } // Constant Pool + + 0x0000; // access + #0;// this_cpx + #3;// super_cpx + + [] { // Interfaces + #0; + #3; + } // Interfaces + + [] { // fields + { // Member + 0x0000; // access + #0; // name_cpx + #0; // sig_cpx + [] { // Attributes + } // Attributes + } // Member + } // fields + + [] { // methods + { // Member + 0x0000; // access + #0; // name_cpx + #0; // sig_cpx + [] { // Attributes + Attr(#1) { // Code + 0; // max_stack + 0; // max_locals + Bytes[]{ + } + [] { // Traps + } // end Traps + [] { // Attributes + } // Attributes + } // end Code + } // Attributes + } // Member + } // methods + + [] { // Attributes + } // Attributes +} // end class Malformed + diff --git a/test/langtools/tools/javap/malformed/MalformedTest.java b/test/langtools/tools/javap/malformed/MalformedTest.java new file mode 100644 index 00000000000..ad7ba221211 --- /dev/null +++ b/test/langtools/tools/javap/malformed/MalformedTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8294969 + * @summary javap test safeguarding malformed class file + * @build Malformed + * @run main MalformedTest + * @modules jdk.jdeps/com.sun.tools.javap + */ +import java.io.PrintWriter; +import java.io.StringWriter; + +public class MalformedTest { + + public static void main(String args[]) throws Exception { + var sw = new StringWriter(); + int res = com.sun.tools.javap.Main.run( + new String[]{"-c", "-v", System.getProperty("test.classes") + "/Malformed.class"}, + new PrintWriter(sw)); + System.out.println(sw); + if (res == 0) + throw new AssertionError("Failure exit code expected"); + if (sw.toString().contains("Fatal error")) + throw new AssertionError("Unguarded fatal error"); + if (sw.toString().contains("error while reading constant pool")) + throw new AssertionError("Unguarded constant pool error"); + } +}