diff --git a/src/java.base/share/classes/java/lang/classfile/Annotation.java b/src/java.base/share/classes/java/lang/classfile/Annotation.java index 3e7548d0859..28c3672bf91 100644 --- a/src/java.base/share/classes/java/lang/classfile/Annotation.java +++ b/src/java.base/share/classes/java/lang/classfile/Annotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -51,7 +51,6 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Annotation - extends WritableElement permits TypeAnnotation, AnnotationImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java b/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java index 41acb18e788..80adb07ec4b 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -41,7 +41,6 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface AnnotationElement - extends WritableElement permits AnnotationImpl.AnnotationElementImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java index 2882296b6bc..919c8a0441d 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -49,7 +49,7 @@ import jdk.internal.javac.PreviewFeature; * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) -public sealed interface AnnotationValue extends WritableElement +public sealed interface AnnotationValue permits AnnotationValue.OfAnnotation, AnnotationValue.OfArray, AnnotationValue.OfConstant, AnnotationValue.OfClass, AnnotationValue.OfEnum { diff --git a/src/java.base/share/classes/java/lang/classfile/Attribute.java b/src/java.base/share/classes/java/lang/classfile/Attribute.java index ad67bdf5365..718f164e8ef 100644 --- a/src/java.base/share/classes/java/lang/classfile/Attribute.java +++ b/src/java.base/share/classes/java/lang/classfile/Attribute.java @@ -80,7 +80,7 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface Attribute> - extends WritableElement + extends ClassFileElement permits AnnotationDefaultAttribute, BootstrapMethodsAttribute, CharacterRangeTableAttribute, CodeAttribute, CompilationIDAttribute, ConstantValueAttribute, DeprecatedAttribute, EnclosingMethodAttribute, diff --git a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java index c472dca8530..5ff3c449fe9 100644 --- a/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/BootstrapMethodEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -43,7 +43,6 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface BootstrapMethodEntry - extends WritableElement permits BootstrapMethodEntryImpl { /** diff --git a/src/java.base/share/classes/java/lang/classfile/BufWriter.java b/src/java.base/share/classes/java/lang/classfile/BufWriter.java index 11d6a4501f0..c71b44e7c02 100644 --- a/src/java.base/share/classes/java/lang/classfile/BufWriter.java +++ b/src/java.base/share/classes/java/lang/classfile/BufWriter.java @@ -24,8 +24,6 @@ */ package java.lang.classfile; -import java.util.List; - import java.lang.classfile.constantpool.ConstantPool; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.PoolEntry; @@ -110,13 +108,6 @@ public sealed interface BufWriter */ void writeBytes(byte[] arr); - /** - * Write the contents of another {@link BufWriter} to the buffer - * - * @param other the other {@linkplain BufWriter} - */ - void writeBytes(BufWriter other); - /** * Write a range of a byte array to the buffer * @@ -166,38 +157,8 @@ public sealed interface BufWriter */ void writeIndexOrZero(PoolEntry entry); - /** - * Write a list of entities to the buffer. The length of the list is - * written as a {@code u2}, followed by the bytes corresponding to each - * element in the list. Writing of the entities is delegated to the entry. - * - * @param list the entities - * @param the type of entity - */ - > void writeList(List list); - - /** - * Write a list of constant pool entry indexes to the buffer. The length - * of the list is written as a {@code u2}, followed by a {@code u2} for each - * entry in the list. - * - * @param list the list of entries - * @throws IllegalArgumentException if any entry has invalid index - */ - void writeListIndices(List list); - /** * {@return the number of bytes that have been written to the buffer} */ int size(); - - /** - * Copy the contents of the buffer into a byte array. - * - * @param array the byte array - * @param bufferOffset the offset into the array at which to write the - * contents of the buffer - * @throws IndexOutOfBoundsException if copying outside of the array bounds - */ - void copyTo(byte[] array, int bufferOffset); } diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java b/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java index 6452f52e042..a4a8203038f 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFileElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -39,6 +39,6 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ClassFileElement - permits AttributedElement, CompoundElement, WritableElement, + permits AttributedElement, CompoundElement, Attribute, ClassElement, CodeElement, FieldElement, MethodElement { } diff --git a/src/java.base/share/classes/java/lang/classfile/ClassReader.java b/src/java.base/share/classes/java/lang/classfile/ClassReader.java index ef4a36729e6..735aae444fc 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassReader.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassReader.java @@ -189,19 +189,4 @@ public sealed interface ClassReader extends ConstantPool * @param len the length of the range */ void copyBytesTo(BufWriter buf, int offset, int len); - - /** - * Compare a range of bytes from the classfile to a range of bytes within - * a {@link BufWriter}. - * - * @param bufWriter the {@linkplain BufWriter} - * @param bufWriterOffset the offset within the {@linkplain BufWriter} - * @param classReaderOffset the offset within the classfile - * @param length the length of the range - * @return whether the two ranges were identical - */ - boolean compare(BufWriter bufWriter, - int bufWriterOffset, - int classReaderOffset, - int length); } diff --git a/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java b/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java index 31544a0ba92..9fe492dc22c 100644 --- a/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java +++ b/src/java.base/share/classes/java/lang/classfile/CustomAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -59,12 +59,6 @@ public abstract non-sealed class CustomAttribute> return mapper.name(); } - @Override - @SuppressWarnings("unchecked") - public final void writeTo(BufWriter buf) { - mapper.writeAttribute(buf, (T) this); - } - @Override public String toString() { return String.format("CustomAttribute[name=%s]", mapper.name()); diff --git a/src/java.base/share/classes/java/lang/classfile/FieldModel.java b/src/java.base/share/classes/java/lang/classfile/FieldModel.java index 35465dfe97d..e14f264ca2a 100644 --- a/src/java.base/share/classes/java/lang/classfile/FieldModel.java +++ b/src/java.base/share/classes/java/lang/classfile/FieldModel.java @@ -42,7 +42,7 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface FieldModel - extends WritableElement, CompoundElement, AttributedElement, ClassElement + extends CompoundElement, AttributedElement, ClassElement permits BufferedFieldBuilder.Model, FieldImpl { /** {@return the access flags} */ diff --git a/src/java.base/share/classes/java/lang/classfile/MethodModel.java b/src/java.base/share/classes/java/lang/classfile/MethodModel.java index 3d91683e218..651bc194ee3 100644 --- a/src/java.base/share/classes/java/lang/classfile/MethodModel.java +++ b/src/java.base/share/classes/java/lang/classfile/MethodModel.java @@ -42,7 +42,7 @@ import jdk.internal.javac.PreviewFeature; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface MethodModel - extends WritableElement, CompoundElement, AttributedElement, ClassElement + extends CompoundElement, AttributedElement, ClassElement permits BufferedMethodBuilder.Model, MethodImpl { /** {@return the access flags} */ diff --git a/src/java.base/share/classes/java/lang/classfile/WritableElement.java b/src/java.base/share/classes/java/lang/classfile/WritableElement.java deleted file mode 100644 index 9a4db4e370f..00000000000 --- a/src/java.base/share/classes/java/lang/classfile/WritableElement.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2022, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -package java.lang.classfile; - -import java.lang.classfile.constantpool.ConstantPoolBuilder; -import java.lang.classfile.constantpool.PoolEntry; -import jdk.internal.classfile.impl.DirectFieldBuilder; -import jdk.internal.classfile.impl.DirectMethodBuilder; -import jdk.internal.javac.PreviewFeature; - -/** - * A classfile element that can encode itself as a stream of bytes in the - * encoding expected by the classfile format. - * - * @param the type of the entity - * - * @sealedGraph - * @since 22 - */ -@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) -public sealed interface WritableElement extends ClassFileElement - permits Annotation, AnnotationElement, AnnotationValue, Attribute, - PoolEntry, BootstrapMethodEntry, FieldModel, MethodModel, - ConstantPoolBuilder, DirectFieldBuilder, DirectMethodBuilder { - /** - * Writes the element to the specified writer - * - * @param buf the writer - */ - void writeTo(BufWriter buf); -} diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index a43e6f102ed..c0927175476 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -33,13 +33,11 @@ import java.lang.constant.MethodTypeDesc; import java.util.List; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassBuilder; import java.lang.classfile.ClassModel; import jdk.internal.classfile.impl.ClassReaderImpl; import java.lang.constant.ModuleDesc; import java.lang.constant.PackageDesc; -import java.lang.classfile.WritableElement; import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl; import jdk.internal.classfile.impl.AbstractPoolEntry.NameAndTypeEntryImpl; import jdk.internal.classfile.impl.SplitConstantPool; @@ -61,7 +59,7 @@ import static java.util.Objects.requireNonNull; */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) public sealed interface ConstantPoolBuilder - extends ConstantPool, WritableElement + extends ConstantPool permits SplitConstantPool, TemporaryConstantPool { /** diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java index 49bd978e56a..c8b74a13928 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -24,7 +24,6 @@ */ package java.lang.classfile.constantpool; -import java.lang.classfile.WritableElement; import jdk.internal.javac.PreviewFeature; /** @@ -34,7 +33,7 @@ import jdk.internal.javac.PreviewFeature; * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) -public sealed interface PoolEntry extends WritableElement +public sealed interface PoolEntry permits AnnotationConstantValueEntry, DynamicConstantPoolEntry, LoadableConstantEntry, MemberRefEntry, ModuleEntry, NameAndTypeEntry, PackageEntry { diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java index cd37ab94992..4d3d7553867 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -24,9 +24,6 @@ */ package java.lang.classfile.instruction; -import java.lang.constant.ClassDesc; - -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; @@ -34,6 +31,8 @@ import java.lang.classfile.Label; import java.lang.classfile.PseudoInstruction; import java.lang.classfile.attribute.LocalVariableTableAttribute; import java.lang.classfile.constantpool.Utf8Entry; +import java.lang.constant.ClassDesc; + import jdk.internal.classfile.impl.AbstractPseudoInstruction; import jdk.internal.classfile.impl.BoundLocalVariable; import jdk.internal.classfile.impl.TemporaryConstantPool; @@ -84,14 +83,6 @@ public sealed interface LocalVariable extends PseudoInstruction */ Label endScope(); - /** - * Writes the local variable to the specified writer - * - * @param buf the writer - * @return true if the variable has been written - */ - boolean writeTo(BufWriter buf); - /** * {@return a local variable pseudo-instruction} * diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java index 1415d0bb57c..4409abe6db2 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -24,7 +24,6 @@ */ package java.lang.classfile.instruction; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; @@ -33,6 +32,7 @@ import java.lang.classfile.PseudoInstruction; import java.lang.classfile.Signature; import java.lang.classfile.attribute.LocalVariableTypeTableAttribute; import java.lang.classfile.constantpool.Utf8Entry; + import jdk.internal.classfile.impl.AbstractPseudoInstruction; import jdk.internal.classfile.impl.BoundLocalVariableType; import jdk.internal.classfile.impl.TemporaryConstantPool; @@ -81,14 +81,6 @@ public sealed interface LocalVariableType extends PseudoInstruction */ Label endScope(); - /** - * Writes the local variable to the specified writer - * - * @param buf the writer - * @return true if the variable has been written - */ - boolean writeTo(BufWriter buf); - /** * {@return a local variable type pseudo-instruction} * diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java index 9bb3f275ba1..0029b503d7a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -101,7 +101,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, AnnotationDefaultAttribute attr) { - attr.defaultValue().writeTo(buf); + AnnotationReader.writeAnnotationValue((BufWriterImpl) buf, attr.defaultValue()); } } @@ -119,7 +119,11 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, BootstrapMethodsAttribute attr) { - buf.writeList(attr.bootstrapMethods()); + var b = (BufWriterImpl) buf; + b.writeU2(attr.bootstrapMethodsSize()); + for (var bsm : attr.bootstrapMethods()) { + ((BootstrapMethodEntryImpl) bsm).writeTo(b); + } } } @@ -254,7 +258,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, ExceptionsAttribute attr) { - buf.writeListIndices(attr.exceptions()); + Util.writeListIndices(buf, attr.exceptions()); } } @@ -408,19 +412,19 @@ public sealed abstract class AbstractAttributeMapper> for (ModuleExportInfo export : attr.exports()) { buf.writeIndex(export.exportedPackage()); buf.writeU2(export.exportsFlagsMask()); - buf.writeListIndices(export.exportsTo()); + Util.writeListIndices(buf, export.exportsTo()); } buf.writeU2(attr.opens().size()); for (ModuleOpenInfo open : attr.opens()) { buf.writeIndex(open.openedPackage()); buf.writeU2(open.opensFlagsMask()); - buf.writeListIndices(open.opensTo()); + Util.writeListIndices(buf, open.opensTo()); } - buf.writeListIndices(attr.uses()); + Util.writeListIndices(buf, attr.uses()); buf.writeU2(attr.provides().size()); for (ModuleProvideInfo provide : attr.provides()) { buf.writeIndex(provide.provides()); - buf.writeListIndices(provide.providesWith()); + Util.writeListIndices(buf, provide.providesWith()); } } } @@ -482,7 +486,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) { - buf.writeListIndices(attr.packages()); + Util.writeListIndices(buf, attr.packages()); } } @@ -554,7 +558,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, NestMembersAttribute attr) { - buf.writeListIndices(attr.nestMembers()); + Util.writeListIndices(buf, attr.nestMembers()); } } @@ -572,7 +576,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) { - buf.writeListIndices(attr.permittedSubclasses()); + Util.writeListIndices(buf, attr.permittedSubclasses()); } } @@ -595,7 +599,7 @@ public sealed abstract class AbstractAttributeMapper> for (RecordComponentInfo info : components) { buf.writeIndex(info.name()); buf.writeIndex(info.descriptor()); - buf.writeList(info.attributes()); + Util.writeAttributes((BufWriterImpl) buf, info.attributes()); } } } @@ -614,7 +618,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) { - buf.writeList(attr.annotations()); + AnnotationReader.writeAnnotations(buf, attr.annotations()); } } @@ -635,7 +639,7 @@ public sealed abstract class AbstractAttributeMapper> List> lists = attr.parameterAnnotations(); buf.writeU1(lists.size()); for (List list : lists) - buf.writeList(list); + AnnotationReader.writeAnnotations(buf, list); } } @@ -653,7 +657,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) { - buf.writeList(attr.annotations()); + AnnotationReader.writeAnnotations(buf, attr.annotations()); } } @@ -671,7 +675,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) { - buf.writeList(attr.annotations()); + AnnotationReader.writeAnnotations(buf, attr.annotations()); } } @@ -692,7 +696,7 @@ public sealed abstract class AbstractAttributeMapper> List> lists = attr.parameterAnnotations(); buf.writeU1(lists.size()); for (List list : lists) - buf.writeList(list); + AnnotationReader.writeAnnotations(buf, list); } } @@ -710,7 +714,7 @@ public sealed abstract class AbstractAttributeMapper> @Override protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) { - buf.writeList(attr.annotations()); + AnnotationReader.writeAnnotations(buf, attr.annotations()); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractBoundLocalVariable.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractBoundLocalVariable.java index d3f49e3168a..dcbd8c8fee8 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractBoundLocalVariable.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractBoundLocalVariable.java @@ -24,12 +24,11 @@ */ package jdk.internal.classfile.impl; -import java.lang.classfile.BufWriter; import java.lang.classfile.Label; import java.lang.classfile.constantpool.Utf8Entry; public class AbstractBoundLocalVariable - extends AbstractElement { + extends AbstractElement implements Util.WritableLocalVariable { protected final CodeImpl code; protected final int offset; private Utf8Entry nameEntry; @@ -80,8 +79,9 @@ public class AbstractBoundLocalVariable return code.classReader.readU2(offset + 8); } - public boolean writeTo(BufWriter b) { - var lc = ((BufWriterImpl)b).labelContext(); + @Override + public boolean writeLocalTo(BufWriterImpl b) { + var lc = b.labelContext(); int startBci = lc.labelToBci(startScope()); int endBci = lc.labelToBci(endScope()); if (startBci == -1 || endBci == -1) { 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 f846ca6fa90..c6e6c4dce57 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 @@ -34,7 +34,6 @@ import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantDynamicEntry; import java.lang.classfile.constantpool.ConstantPool; import java.lang.classfile.constantpool.ConstantPoolBuilder; -import java.lang.classfile.BufWriter; import java.lang.classfile.constantpool.DoubleEntry; import java.lang.classfile.constantpool.FieldRefEntry; import java.lang.classfile.constantpool.FloatEntry; @@ -123,6 +122,8 @@ public abstract sealed class AbstractPoolEntry { return (tag == ClassFile.TAG_LONG || tag == ClassFile.TAG_DOUBLE) ? 2 : 1; } + abstract void writeTo(BufWriterImpl buf); + abstract PoolEntry clone(ConstantPoolBuilder cp); public static final class Utf8EntryImpl extends AbstractPoolEntry implements Utf8Entry { @@ -407,7 +408,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { if (rawBytes != null) { pool.writeU1(tag); pool.writeU2(rawLen); @@ -478,7 +479,7 @@ public abstract sealed class AbstractPoolEntry { return ref1; } - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeU2(ref1.index()); } @@ -508,7 +509,7 @@ public abstract sealed class AbstractPoolEntry { return ref2; } - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeU2(ref1.index()); pool.writeU2(ref2.index()); @@ -814,7 +815,7 @@ public abstract sealed class AbstractPoolEntry { return nameAndType; } - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeU2(bsmIndex); pool.writeU2(nameAndType.index()); @@ -919,7 +920,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeU1(refKind); pool.writeU2(reference.index()); @@ -1069,7 +1070,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeInt(val); } @@ -1102,7 +1103,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeFloat(val); } @@ -1134,7 +1135,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeLong(val); } @@ -1166,7 +1167,7 @@ public abstract sealed class AbstractPoolEntry { } @Override - public void writeTo(BufWriter pool) { + void writeTo(BufWriterImpl pool) { pool.writeU1(tag); pool.writeDouble(val); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPseudoInstruction.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPseudoInstruction.java index ffc36037905..00d817b8cb0 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPseudoInstruction.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPseudoInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -154,7 +154,8 @@ public abstract sealed class AbstractPseudoInstruction } - private abstract static sealed class AbstractLocalPseudo extends AbstractPseudoInstruction { + private abstract static sealed class AbstractLocalPseudo extends AbstractPseudoInstruction + implements Util.WritableLocalVariable { protected final int slot; protected final Utf8Entry name; protected final Utf8Entry descriptor; @@ -189,8 +190,9 @@ public abstract sealed class AbstractPseudoInstruction return endScope; } - public boolean writeTo(BufWriter b) { - var lc = ((BufWriterImpl)b).labelContext(); + @Override + public boolean writeLocalTo(BufWriterImpl b) { + var lc = b.labelContext(); int startBci = lc.labelToBci(startScope()); int endBci = lc.labelToBci(endScope()); if (startBci == -1 || endBci == -1) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractUnboundModel.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractUnboundModel.java index 5aebec8ab40..788bdffe1cd 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractUnboundModel.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractUnboundModel.java @@ -35,7 +35,7 @@ import java.lang.classfile.CompoundElement; public abstract sealed class AbstractUnboundModel extends AbstractElement - implements CompoundElement, AttributedElement + implements CompoundElement, AttributedElement, Util.Writable permits BufferedCodeBuilder.Model, BufferedFieldBuilder.Model, BufferedMethodBuilder.Model { private final List elements; private List> attributes; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java index 4fc2d5cf63b..8290fcd286e 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -32,7 +32,7 @@ import java.util.List; import static java.lang.classfile.ClassFile.*; -public final class AnnotationImpl implements Annotation { +public final class AnnotationImpl implements Annotation, Util.Writable { private final Utf8Entry className; private final List elements; @@ -53,9 +53,13 @@ public final class AnnotationImpl implements Annotation { } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeIndex(className()); - buf.writeList(elements()); + buf.writeU2(elements().size()); + for (var e : elements) { + buf.writeIndex(e.name()); + AnnotationReader.writeAnnotationValue(buf, e.value()); + } } @Override @@ -81,16 +85,16 @@ public final class AnnotationImpl implements Annotation { public record AnnotationElementImpl(Utf8Entry name, AnnotationValue value) - implements AnnotationElement { + implements AnnotationElement, Util.Writable { @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeIndex(name()); - value().writeTo(buf); + AnnotationReader.writeAnnotationValue(buf, value()); } } - public sealed interface OfConstantImpl extends AnnotationValue.OfConstant + public sealed interface OfConstantImpl extends AnnotationValue.OfConstant, Util.Writable permits AnnotationImpl.OfStringImpl, AnnotationImpl.OfDoubleImpl, AnnotationImpl.OfFloatImpl, AnnotationImpl.OfLongImpl, AnnotationImpl.OfIntegerImpl, AnnotationImpl.OfShortImpl, @@ -98,7 +102,7 @@ public final class AnnotationImpl implements Annotation { AnnotationImpl.OfBooleanImpl { @Override - default void writeTo(BufWriter buf) { + default void writeTo(BufWriterImpl buf) { buf.writeU1(tag()); buf.writeIndex(constant()); } @@ -237,7 +241,7 @@ public final class AnnotationImpl implements Annotation { } public record OfArrayImpl(List values) - implements AnnotationValue.OfArray { + implements AnnotationValue.OfArray, Util.Writable { public OfArrayImpl(List values) { this.values = List.copyOf(values); @@ -249,22 +253,25 @@ public final class AnnotationImpl implements Annotation { } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeU1(tag()); - buf.writeList(values); + buf.writeU2(values.size()); + for (var e : values) { + AnnotationReader.writeAnnotationValue(buf, e); + } } } public record OfEnumImpl(Utf8Entry className, Utf8Entry constantName) - implements AnnotationValue.OfEnum { + implements AnnotationValue.OfEnum, Util.Writable { @Override public char tag() { return AEV_ENUM; } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeU1(tag()); buf.writeIndex(className); buf.writeIndex(constantName); @@ -273,29 +280,29 @@ public final class AnnotationImpl implements Annotation { } public record OfAnnotationImpl(Annotation annotation) - implements AnnotationValue.OfAnnotation { + implements AnnotationValue.OfAnnotation, Util.Writable { @Override public char tag() { return AEV_ANNOTATION; } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeU1(tag()); - annotation.writeTo(buf); + AnnotationReader.writeAnnotation(buf, annotation); } } public record OfClassImpl(Utf8Entry className) - implements AnnotationValue.OfClass { + implements AnnotationValue.OfClass, Util.Writable { @Override public char tag() { return AEV_CLASS; } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeU1(tag()); buf.writeIndex(className); } 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 7b5920b3e78..2ada13aaba8 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 @@ -28,6 +28,7 @@ package jdk.internal.classfile.impl; import java.lang.classfile.Annotation; import java.lang.classfile.AnnotationElement; import java.lang.classfile.AnnotationValue; +import java.lang.classfile.BufWriter; import java.lang.classfile.ClassReader; import java.lang.classfile.constantpool.*; import java.lang.classfile.TypeAnnotation; @@ -39,7 +40,7 @@ import java.lang.classfile.Label; import java.lang.classfile.constantpool.Utf8Entry; import jdk.internal.access.SharedSecrets; -class AnnotationReader { +public final class AnnotationReader { private AnnotationReader() { } public static List readAnnotations(ClassReader classReader, int p) { @@ -280,4 +281,24 @@ class AnnotationReader { p = skipElementValuePairs(classReader, p); return p; } + + public static void writeAnnotation(BufWriterImpl buf, Annotation annotation) { + // handles annotations and type annotations + // TODO annotation cleanup later + ((Util.Writable) annotation).writeTo(buf); + } + + public static void writeAnnotations(BufWriter buf, List list) { + // handles annotations and type annotations + var internalBuf = (BufWriterImpl) buf; + internalBuf.writeU2(list.size()); + for (var e : list) { + writeAnnotation(internalBuf, e); + } + } + + public static void writeAnnotationValue(BufWriterImpl buf, AnnotationValue value) { + // TODO annotation cleanup later + ((Util.Writable) value).writeTo(buf); + } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java index be5176ad1df..ba51474c131 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -29,7 +29,6 @@ import java.util.List; import java.lang.classfile.Attribute; import java.lang.classfile.AttributeMapper; -import java.lang.classfile.BufWriter; public class AttributeHolder { private final List> attributes = new ArrayList<>(); @@ -50,10 +49,8 @@ public class AttributeHolder { return attributes.size(); } - public void writeTo(BufWriter buf) { - buf.writeU2(attributes.size()); - for (Attribute a : attributes) - a.writeTo(buf); + public void writeTo(BufWriterImpl buf) { + Util.writeAttributes(buf, attributes); } boolean isPresent(AttributeMapper am) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BootstrapMethodEntryImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BootstrapMethodEntryImpl.java index d6876a82a9c..267c11c5845 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BootstrapMethodEntryImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BootstrapMethodEntryImpl.java @@ -28,7 +28,6 @@ import java.util.List; import java.lang.classfile.constantpool.ConstantPool; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.BufWriter; import java.lang.classfile.constantpool.LoadableConstantEntry; import java.lang.classfile.constantpool.MethodHandleEntry; @@ -87,9 +86,8 @@ public final class BootstrapMethodEntryImpl implements BootstrapMethodEntry { return hash; } - @Override - public void writeTo(BufWriter writer) { + void writeTo(BufWriterImpl writer) { writer.writeIndex(bootstrapMethod()); - writer.writeListIndices(arguments()); + Util.writeListIndices(writer, arguments()); } } 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 6a23be54f48..a0428d9d09d 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 @@ -48,7 +48,7 @@ import static java.lang.classfile.Attributes.*; public abstract sealed class BoundAttribute> extends AbstractElement - implements Attribute { + implements Attribute, Util.Writable { static final int NAME_AND_LENGTH_PREFIX = 6; private final AttributeMapper mapper; @@ -101,7 +101,7 @@ public abstract sealed class BoundAttribute> @Override @SuppressWarnings("unchecked") - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { if (!buf.canWriteDirect(classReader)) attributeMapper().writeAttribute(buf, (T) this); else diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java index 87161588203..ac34d78e0e5 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java @@ -27,10 +27,8 @@ package jdk.internal.classfile.impl; import java.nio.ByteBuffer; import java.util.Arrays; -import java.util.List; import java.lang.classfile.BufWriter; -import java.lang.classfile.WritableElement; import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantPool; import java.lang.classfile.constantpool.ConstantPoolBuilder; @@ -126,10 +124,8 @@ public final class BufWriterImpl implements BufWriter { writeBytes(arr, 0, arr.length); } - @Override - public void writeBytes(BufWriter other) { - BufWriterImpl o = (BufWriterImpl) other; - writeBytes(o.elems, 0, o.offset); + public void writeBytes(BufWriterImpl other) { + writeBytes(other.elems, 0, other.offset); } @Override @@ -175,7 +171,6 @@ public final class BufWriterImpl implements BufWriter { return ByteBuffer.wrap(elems, 0, offset).slice(); } - @Override public void copyTo(byte[] array, int bufferOffset) { System.arraycopy(elems, 0, array, bufferOffset, size()); } @@ -198,20 +193,4 @@ public final class BufWriterImpl implements BufWriter { else writeIndex(entry); } - - @Override - public> void writeList(List list) { - writeU2(list.size()); - for (T t : list) { - t.writeTo(this); - } - } - - @Override - public void writeListIndices(List list) { - writeU2(list.size()); - for (PoolEntry info : list) { - writeIndex(info); - } - } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java index c3a601fa1df..4743c58607c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java @@ -24,7 +24,6 @@ */ package jdk.internal.classfile.impl; -import java.lang.classfile.BufWriter; import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; @@ -201,7 +200,8 @@ public final class BufferedCodeBuilder }); } - public void writeTo(BufWriter buf) { + @Override + public void writeTo(BufWriterImpl buf) { DirectCodeBuilder.build(methodInfo, cb -> elements.forEach(cb), constantPool, context, null).writeTo(buf); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java index a92513390b4..660a999f2a3 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java @@ -112,7 +112,7 @@ public final class BufferedFieldBuilder } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { DirectFieldBuilder fb = new DirectFieldBuilder(constantPool, context, name, desc, null); elements.forEach(fb); fb.writeTo(buf); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java index f92ee1adf34..880c6717db8 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java @@ -33,7 +33,6 @@ import java.util.function.Consumer; import java.lang.classfile.AccessFlags; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassModel; import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeModel; @@ -211,7 +210,7 @@ public final class BufferedMethodBuilder } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { DirectMethodBuilder mb = new DirectMethodBuilder(constantPool, context, name, desc, methodFlags(), null); elements.forEach(mb); mb.writeTo(buf); 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 25d4e2e68e8..9695b16ad51 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 @@ -321,12 +321,13 @@ public final class ClassReaderImpl return containedClass; } - boolean writeBootstrapMethods(BufWriter buf) { + boolean writeBootstrapMethods(BufWriterImpl buf) { Optional a = containedClass.findAttribute(Attributes.bootstrapMethods()); if (a.isEmpty()) return false; - a.get().writeTo(buf); + // BootstrapMethodAttribute implementations are all internal writable + ((Util.Writable) a.get()).writeTo(buf); return true; } @@ -465,13 +466,12 @@ public final class ClassReaderImpl return entryByIndex(index, cls); } - @Override - public boolean compare(BufWriter bufWriter, + public boolean compare(BufWriterImpl bufWriter, int bufWriterOffset, int classReaderOffset, int length) { try { - return Arrays.equals(((BufWriterImpl) bufWriter).elems, + return Arrays.equals(bufWriter.elems, bufWriterOffset, bufWriterOffset + length, buffer, classReaderOffset, classReaderOffset + length); } catch (IndexOutOfBoundsException e) { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index 4b2a21072f0..7669cbfdd30 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -141,7 +141,7 @@ public final class CodeImpl } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { if (buf.canWriteDirect(classReader)) { super.writeTo(buf); } @@ -154,7 +154,7 @@ public final class CodeImpl } }, (SplitConstantPool)buf.constantPool(), - ((BufWriterImpl)buf).context(), + buf.context(), null).writeTo(buf); } } @@ -210,7 +210,7 @@ public final class CodeImpl return exceptionTable; } - public boolean compareCodeBytes(BufWriter buf, int offset, int len) { + public boolean compareCodeBytes(BufWriterImpl buf, int offset, int len) { return codeLength == len && classReader.compare(buf, offset, codeStart, codeLength); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java index 915c3ad8cf4..21fde0f6002 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -31,7 +31,6 @@ import java.util.Collections; import java.util.List; import java.util.function.Consumer; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassBuilder; import java.lang.classfile.ClassElement; import java.lang.classfile.ClassModel; @@ -44,7 +43,6 @@ import java.lang.classfile.FieldTransform; import java.lang.classfile.MethodBuilder; import java.lang.classfile.MethodModel; import java.lang.classfile.MethodTransform; -import java.lang.classfile.WritableElement; import java.lang.classfile.constantpool.Utf8Entry; public final class DirectClassBuilder @@ -52,8 +50,8 @@ public final class DirectClassBuilder implements ClassBuilder { final ClassEntry thisClassEntry; - private final List> fields = new ArrayList<>(); - private final List> methods = new ArrayList<>(); + private final List fields = new ArrayList<>(); + private final List methods = new ArrayList<>(); private ClassEntry superclassEntry; private List interfaceEntries; private int majorVersion; @@ -78,7 +76,7 @@ public final class DirectClassBuilder if (element instanceof AbstractElement ae) { ae.writeTo(this); } else { - writeAttribute((CustomAttribute)element); + writeAttribute((CustomAttribute) element); } return this; } @@ -120,12 +118,12 @@ public final class DirectClassBuilder // internal / for use by elements - public ClassBuilder withField(WritableElement field) { + ClassBuilder withField(Util.Writable field) { fields.add(field); return this; } - public ClassBuilder withMethod(WritableElement method) { + ClassBuilder withMethod(Util.Writable method) { methods.add(method); return this; } @@ -172,13 +170,13 @@ public final class DirectClassBuilder // We maintain two writers, and then we join them at the end int size = sizeHint == 0 ? 256 : sizeHint; - BufWriter head = new BufWriterImpl(constantPool, context, size); + BufWriterImpl head = new BufWriterImpl(constantPool, context, size); BufWriterImpl tail = new BufWriterImpl(constantPool, context, size, thisClassEntry, majorVersion); // The tail consists of fields and methods, and attributes // This should trigger all the CP/BSM mutation - tail.writeList(fields); - tail.writeList(methods); + Util.writeList(tail, fields); + Util.writeList(tail, methods); int attributesOffset = tail.size(); attributes.writeTo(tail); @@ -197,7 +195,7 @@ public final class DirectClassBuilder head.writeU2(flags); head.writeIndex(thisClassEntry); head.writeIndexOrZero(superclass); - head.writeListIndices(ies); + Util.writeListIndices(head, ies); // Join head and tail into an exact-size buffer byte[] result = new byte[head.size() + tail.size()]; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index 0b6549a82da..536750ebd2f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -24,7 +24,6 @@ */ package jdk.internal.classfile.impl; -import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -36,20 +35,17 @@ import java.util.function.Function; import java.lang.classfile.Attribute; import java.lang.classfile.Attributes; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.CustomAttribute; -import java.lang.classfile.Instruction; import java.lang.classfile.Label; import java.lang.classfile.Opcode; import java.lang.classfile.TypeKind; import java.lang.classfile.instruction.SwitchCase; import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.attribute.LineNumberTableAttribute; -import java.lang.classfile.attribute.StackMapTableAttribute; import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.DoubleEntry; @@ -83,7 +79,7 @@ public final class DirectCodeBuilder private final boolean transformFwdJumps, transformBackJumps; private final Label startLabel, endLabel; final MethodInfo methodInfo; - final BufWriter bytecodesBufWriter; + final BufWriterImpl bytecodesBufWriter; private CodeAttribute mruParent; private int[] mruParentTable; private Map parentMap; @@ -100,7 +96,7 @@ public final class DirectCodeBuilder allocLocal(TypeKind) bumps by nSlots */ - public static Attribute build(MethodInfo methodInfo, + public static UnboundAttribute build(MethodInfo methodInfo, Consumer handler, SplitConstantPool constantPool, ClassFileImpl context, @@ -144,7 +140,7 @@ public final class DirectCodeBuilder if (element instanceof AbstractElement ae) { ae.writeTo(this); } else { - writeAttribute((CustomAttribute)element); + writeAttribute((CustomAttribute) element); } return this; } @@ -193,9 +189,9 @@ public final class DirectCodeBuilder return methodInfo; } - private Attribute content = null; + private UnboundAttribute content = null; - private void writeExceptionHandlers(BufWriter buf) { + private void writeExceptionHandlers(BufWriterImpl buf) { int pos = buf.size(); int handlersSize = handlers.size(); buf.writeU2(handlersSize); @@ -233,7 +229,7 @@ public final class DirectCodeBuilder Attribute a = new UnboundAttribute.AdHocAttribute<>(Attributes.characterRangeTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { int pos = b.size(); int crSize = characterRanges.size(); b.writeU2(crSize); @@ -264,12 +260,12 @@ public final class DirectCodeBuilder if (!localVariables.isEmpty()) { Attribute a = new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { int pos = b.size(); int lvSize = localVariables.size(); b.writeU2(lvSize); for (LocalVariable l : localVariables) { - if (!l.writeTo(b)) { + if (!Util.writeLocalVariable(b, l)) { if (context.deadLabelsOption() == ClassFile.DeadLabelsOption.DROP_DEAD_LABELS) { lvSize--; } else { @@ -287,12 +283,12 @@ public final class DirectCodeBuilder if (!localVariableTypes.isEmpty()) { Attribute a = new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTypeTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { int pos = b.size(); int lvtSize = localVariableTypes.size(); b.writeU2(localVariableTypes.size()); for (LocalVariableType l : localVariableTypes) { - if (!l.writeTo(b)) { + if (!Util.writeLocalVariable(b, l)) { if (context.deadLabelsOption() == ClassFile.DeadLabelsOption.DROP_DEAD_LABELS) { lvtSize--; } else { @@ -352,8 +348,7 @@ public final class DirectCodeBuilder } @Override - public void writeBody(BufWriter b) { - BufWriterImpl buf = (BufWriterImpl) b; + public void writeBody(BufWriterImpl buf) { buf.setLabelContext(DirectCodeBuilder.this); int codeLength = curPc(); @@ -389,8 +384,8 @@ public final class DirectCodeBuilder buf.writeInt(codeLength); buf.writeBytes(bytecodesBufWriter); - writeExceptionHandlers(b); - attributes.writeTo(b); + writeExceptionHandlers(buf); + attributes.writeTo(buf); buf.setLabelContext(null); } }; @@ -427,12 +422,12 @@ public final class DirectCodeBuilder } @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { throw new UnsupportedOperationException(); } @Override - public void writeTo(BufWriter b) { + public void writeTo(BufWriterImpl b) { b.writeIndex(b.constantPool().utf8Entry(Attributes.NAME_LINE_NUMBER_TABLE)); push(); b.writeInt(buf.size() + 2); @@ -447,7 +442,7 @@ public final class DirectCodeBuilder codeAttributesMatch = cai.codeLength == curPc() && cai.compareCodeBytes(bytecodesBufWriter, 0, codeLength); if (codeAttributesMatch) { - BufWriter bw = new BufWriterImpl(constantPool, context); + var bw = new BufWriterImpl(constantPool, context); writeExceptionHandlers(bw); codeAttributesMatch = cai.classReader.compare(bw, 0, cai.exceptionHandlerPos, bw.size()); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectFieldBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectFieldBuilder.java index 7bdab531e44..ce51bb1d26b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectFieldBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectFieldBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -27,17 +27,15 @@ package jdk.internal.classfile.impl; import java.util.function.Consumer; -import java.lang.classfile.BufWriter; import java.lang.classfile.CustomAttribute; import java.lang.classfile.FieldBuilder; import java.lang.classfile.FieldElement; import java.lang.classfile.FieldModel; -import java.lang.classfile.WritableElement; import java.lang.classfile.constantpool.Utf8Entry; public final class DirectFieldBuilder extends AbstractDirectBuilder - implements TerminalFieldBuilder, WritableElement { + implements TerminalFieldBuilder, Util.Writable { private final Utf8Entry name; private final Utf8Entry desc; private int flags; @@ -59,7 +57,7 @@ public final class DirectFieldBuilder if (element instanceof AbstractElement ae) { ae.writeTo(this); } else { - writeAttribute((CustomAttribute)element); + writeAttribute((CustomAttribute) element); } return this; } @@ -74,7 +72,7 @@ public final class DirectFieldBuilder } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { buf.writeU2(flags); buf.writeIndex(name); buf.writeIndex(desc); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectMethodBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectMethodBuilder.java index a4b3bbe1b84..f79eb0af0cb 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectMethodBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectMethodBuilder.java @@ -28,7 +28,6 @@ package jdk.internal.classfile.impl; import java.lang.constant.MethodTypeDesc; import java.util.function.Consumer; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeModel; @@ -37,12 +36,11 @@ import java.lang.classfile.CustomAttribute; import java.lang.classfile.MethodBuilder; import java.lang.classfile.MethodElement; import java.lang.classfile.MethodModel; -import java.lang.classfile.WritableElement; import java.lang.classfile.constantpool.Utf8Entry; public final class DirectMethodBuilder extends AbstractDirectBuilder - implements TerminalMethodBuilder, WritableElement { + implements TerminalMethodBuilder, Util.Writable { final Utf8Entry name; final Utf8Entry desc; @@ -115,7 +113,7 @@ public final class DirectMethodBuilder if (element instanceof AbstractElement ae) { ae.writeTo(this); } else { - writeAttribute((CustomAttribute)element); + writeAttribute((CustomAttribute) element); } return this; } @@ -148,8 +146,7 @@ public final class DirectMethodBuilder } @Override - public void writeTo(BufWriter b) { - BufWriterImpl buf = (BufWriterImpl) b; + public void writeTo(BufWriterImpl buf) { buf.writeU2(flags); buf.writeIndex(name); buf.writeIndex(desc); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java index ba424c862fd..ab42b96084a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java @@ -33,7 +33,7 @@ import java.lang.classfile.constantpool.Utf8Entry; public final class FieldImpl extends AbstractElement - implements FieldModel { + implements FieldModel, Util.Writable { private final ClassReader reader; private final int startPos, endPos, attributesPos; @@ -78,7 +78,7 @@ public final class FieldImpl } @Override - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { if (buf.canWriteDirect(reader)) { reader.copyBytesTo(buf, startPos, endPos - startPos); } @@ -86,7 +86,7 @@ public final class FieldImpl buf.writeU2(flags().flagsMask()); buf.writeIndex(fieldName()); buf.writeIndex(fieldType()); - buf.writeList(attributes()); + Util.writeAttributes(buf, attributes()); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java index 62a83dffc6e..40223d58d6b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java @@ -34,7 +34,7 @@ import java.util.function.Consumer; public final class MethodImpl extends AbstractElement - implements MethodModel, MethodInfo { + implements MethodModel, MethodInfo, Util.Writable { private final ClassReader reader; private final int startPos, endPos, attributesPos; @@ -101,8 +101,7 @@ public final class MethodImpl } @Override - public void writeTo(BufWriter b) { - BufWriterImpl buf = (BufWriterImpl) b; + public void writeTo(BufWriterImpl buf) { if (buf.canWriteDirect(reader)) { reader.copyBytesTo(buf, startPos, endPos - startPos); } @@ -110,7 +109,7 @@ public final class MethodImpl buf.writeU2(flags().flagsMask()); buf.writeIndex(methodName()); buf.writeIndex(methodType()); - buf.writeList(attributes()); + Util.writeAttributes(buf, attributes()); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java index 6c5a8a266c0..f7905712b18 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java @@ -29,12 +29,10 @@ import java.lang.constant.MethodTypeDesc; import java.util.Arrays; import java.util.List; -import java.lang.classfile.Attribute; import java.lang.classfile.Attributes; import java.lang.classfile.ClassReader; import java.lang.classfile.ClassFile; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.BufWriter; import java.lang.classfile.attribute.BootstrapMethodsAttribute; import java.lang.classfile.constantpool.*; import java.util.Objects; @@ -135,7 +133,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder { return this == other || parent == other; } - public boolean writeBootstrapMethods(BufWriter buf) { + public boolean writeBootstrapMethods(BufWriterImpl buf) { if (bsmSize == 0) return false; int pos = buf.size(); @@ -148,11 +146,11 @@ public final class SplitConstantPool implements ConstantPoolBuilder { buf.patchInt(pos + 6, 2, bsmSize); } else { - Attribute a + UnboundAttribute a = new UnboundAttribute.AdHocAttribute<>(Attributes.bootstrapMethods()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { buf.writeU2(bsmSize); for (int i = 0; i < bsmSize; i++) bootstrapMethodEntry(i).writeTo(buf); @@ -163,8 +161,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder { return true; } - @Override - public void writeTo(BufWriter buf) { + void writeTo(BufWriterImpl buf) { int writeFrom = 1; if (size() >= 65536) { throw new IllegalArgumentException(String.format("Constant pool is too large %d", size())); @@ -175,7 +172,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder { writeFrom = parent.size(); } for (int i = writeFrom; i < size(); ) { - PoolEntry info = entryByIndex(i); + var info = (AbstractPoolEntry) entryByIndex(i); info.writeTo(buf); i += info.width(); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java index 899a43571a3..876cb201b79 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackCounter.java @@ -51,7 +51,7 @@ public final class StackCounter { dcb.methodInfo.methodName().stringValue(), dcb.methodInfo.methodTypeSymbol(), (dcb.methodInfo.methodFlags() & ACC_STATIC) != 0, - ((BufWriterImpl) dcb.bytecodesBufWriter).asByteBuffer(), + dcb.bytecodesBufWriter.asByteBuffer(), dcb.constantPool, dcb.handlers); } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java index 5b103a21f8a..514c1d32f41 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java @@ -152,7 +152,7 @@ public final class StackMapGenerator { dcb.methodInfo.methodName().stringValue(), dcb.methodInfo.methodTypeSymbol(), (dcb.methodInfo.methodFlags() & ACC_STATIC) != 0, - ((BufWriterImpl) dcb.bytecodesBufWriter).asByteBuffer(), + dcb.bytecodesBufWriter.asByteBuffer(), dcb.constantPool, dcb.context, dcb.handlers); @@ -383,7 +383,7 @@ public final class StackMapGenerator { public Attribute stackMapTableAttribute() { return frames.isEmpty() ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.stackMapTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(frames.size()); Frame prevFrame = new Frame(classHierarchy); prevFrame.setLocalsFromArg(methodName, methodDesc, isStatic, thisType); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/TemporaryConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/impl/TemporaryConstantPool.java index e5f7d9cca79..784e844b712 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/TemporaryConstantPool.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/TemporaryConstantPool.java @@ -189,9 +189,4 @@ public final class TemporaryConstantPool implements ConstantPoolBuilder { public boolean canWriteDirect(ConstantPool constantPool) { return false; } - - @Override - public void writeTo(BufWriter buf) { - throw new UnsupportedOperationException(); - } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java index 70b58e423f6..6d71497f693 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -35,7 +35,6 @@ import java.lang.classfile.Attribute; import java.lang.classfile.AttributeMapper; import java.lang.classfile.Attributes; import java.lang.classfile.BootstrapMethodEntry; -import java.lang.classfile.BufWriter; import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.Label; import java.lang.classfile.TypeAnnotation; @@ -95,7 +94,7 @@ import java.lang.classfile.constantpool.Utf8Entry; public abstract sealed class UnboundAttribute> extends AbstractElement - implements Attribute { + implements Attribute, Util.Writable { protected final AttributeMapper mapper; public UnboundAttribute(AttributeMapper mapper) { @@ -114,7 +113,7 @@ public abstract sealed class UnboundAttribute> @Override @SuppressWarnings("unchecked") - public void writeTo(BufWriter buf) { + public void writeTo(BufWriterImpl buf) { mapper.writeAttribute(buf, (T) this); } @@ -752,7 +751,7 @@ public abstract sealed class UnboundAttribute> public record UnboundTypeAnnotation(TargetInfo targetInfo, List targetPath, Utf8Entry className, - List elements) implements TypeAnnotation { + List elements) implements TypeAnnotation, Util.Writable { public UnboundTypeAnnotation(TargetInfo targetInfo, List targetPath, Utf8Entry className, List elements) { @@ -769,8 +768,8 @@ public abstract sealed class UnboundAttribute> } @Override - public void writeTo(BufWriter buf) { - LabelContext lr = ((BufWriterImpl) buf).labelContext(); + public void writeTo(BufWriterImpl buf) { + LabelContext lr = buf.labelContext(); // target_type buf.writeU1(targetInfo.targetType().targetTypeValue()); @@ -818,7 +817,7 @@ public abstract sealed class UnboundAttribute> buf.writeU2(elements.size()); for (AnnotationElement pair : elements()) { buf.writeIndex(pair.name()); - pair.value().writeTo(buf); + AnnotationReader.writeAnnotationValue(buf, pair.value()); } } } @@ -904,10 +903,10 @@ public abstract sealed class UnboundAttribute> super(mapper); } - public abstract void writeBody(BufWriter b); + public abstract void writeBody(BufWriterImpl b); @Override - public void writeTo(BufWriter b) { + public void writeTo(BufWriterImpl b) { b.writeIndex(b.constantPool().utf8Entry(mapper.name())); b.writeInt(0); int start = b.size(); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java index 0e969272c40..079ac9551ab 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java @@ -24,6 +24,9 @@ */ package jdk.internal.classfile.impl; +import java.lang.classfile.CustomAttribute; +import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.constantpool.PoolEntry; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.AbstractList; @@ -47,7 +50,6 @@ import jdk.internal.access.SharedSecrets; import static java.lang.classfile.ClassFile.ACC_STATIC; import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.components.ClassPrinter; -import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.nio.ByteBuffer; import java.util.function.Consumer; @@ -188,6 +190,31 @@ public class Util { return ((AbstractPoolEntry.NameAndTypeEntryImpl)nat).methodTypeSymbol(); } + @SuppressWarnings("unchecked") + private static void writeAttribute(BufWriterImpl writer, Attribute attr) { + if (attr instanceof CustomAttribute ca) { + var mapper = (AttributeMapper) ca.attributeMapper(); + mapper.writeAttribute(writer, (T) ca); + } else { + assert attr instanceof BoundAttribute || attr instanceof UnboundAttribute; + ((Writable) attr).writeTo(writer); + } + } + + public static void writeAttributes(BufWriterImpl buf, List> list) { + buf.writeU2(list.size()); + for (var e : list) { + writeAttribute(buf, e); + } + } + + static void writeList(BufWriterImpl buf, List list) { + buf.writeU2(list.size()); + for (var e : list) { + e.writeTo(buf); + } + } + public static int slotSize(ClassDesc desc) { return switch (desc.descriptorString().charAt(0)) { case 'V' -> 0; @@ -216,7 +243,7 @@ public class Util { clb.withMethod(methodName, methodDesc, acc, mb -> ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.code()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(-1);//max stack b.writeU2(-1);//max locals b.writeInt(bytecode.limit()); @@ -237,4 +264,28 @@ public class Util { } } } + + public static void writeListIndices(BufWriter writer, List list) { + writer.writeU2(list.size()); + for (PoolEntry info : list) { + writer.writeIndex(info); + } + } + + public static boolean writeLocalVariable(BufWriterImpl buf, PseudoInstruction lvOrLvt) { + return ((WritableLocalVariable) lvOrLvt).writeLocalTo(buf); + } + + /** + * A generic interface for objects to write to a + * buf writer. Do not implement unless necessary, + * as this writeTo is public, which can be troublesome. + */ + interface Writable { + void writeTo(BufWriterImpl writer); + } + + interface WritableLocalVariable { + boolean writeLocalTo(BufWriterImpl buf); + } } diff --git a/test/jdk/jdk/classfile/BoundAttributeTest.java b/test/jdk/jdk/classfile/BoundAttributeTest.java index f6d2d0e9010..6a164bec2f9 100644 --- a/test/jdk/jdk/classfile/BoundAttributeTest.java +++ b/test/jdk/jdk/classfile/BoundAttributeTest.java @@ -27,6 +27,7 @@ * @summary Testing BoundAttributes * @run junit BoundAttributeTest */ +import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Assertions; @@ -34,7 +35,6 @@ import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; import java.lang.classfile.Attributes; -import java.lang.classfile.BufWriter; import java.lang.classfile.ClassModel; import java.lang.classfile.ClassFile; import java.lang.classfile.CodeBuilder; @@ -84,7 +84,7 @@ class BoundAttributeTest { var oneClass = cp.classEntry(oneClassString); ((DirectClassBuilder) clb).writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.nestMembers()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(2); b.writeIndex(oneClass); b.writeIndex(oneClassString); diff --git a/test/jdk/jdk/classfile/CorpusTest.java b/test/jdk/jdk/classfile/CorpusTest.java index 2dfbef10d67..a2af1667978 100644 --- a/test/jdk/jdk/classfile/CorpusTest.java +++ b/test/jdk/jdk/classfile/CorpusTest.java @@ -31,6 +31,8 @@ import helpers.ClassRecord; import helpers.ClassRecord.CompatibilityFilter; import helpers.Transforms; +import jdk.internal.classfile.impl.BufWriterImpl; +import jdk.internal.classfile.impl.Util; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.api.parallel.Execution; @@ -85,7 +87,7 @@ class CorpusTest { switch (coe) { case LineNumber ln -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.lineNumberTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(1); b.writeU2(curPc); b.writeU2(ln.line()); @@ -93,16 +95,16 @@ class CorpusTest { }); case LocalVariable lv -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(1); - lv.writeTo(b); + Util.writeLocalVariable(b, lv); } }); case LocalVariableType lvt -> dcob.writeAttribute(new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTypeTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(1); - lvt.writeTo(b); + Util.writeLocalVariable(b, lvt); } }); default -> cob.with(coe); diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java index b1914e6d024..9c7b8d9e72d 100644 --- a/test/jdk/jdk/classfile/LimitsTest.java +++ b/test/jdk/jdk/classfile/LimitsTest.java @@ -28,7 +28,6 @@ * @run junit LimitsTest */ import java.lang.classfile.Attributes; -import java.lang.classfile.BufWriter; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.MethodTypeDesc; @@ -44,6 +43,8 @@ import java.lang.classfile.constantpool.ConstantPoolException; import java.lang.classfile.constantpool.IntegerEntry; import java.lang.classfile.instruction.LocalVariable; import java.util.List; + +import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectCodeBuilder; import jdk.internal.classfile.impl.DirectMethodBuilder; import jdk.internal.classfile.impl.LabelContext; @@ -130,7 +131,7 @@ class LimitsTest { "lookupSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.code()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(-1);//max stack b.writeU2(-1);//max locals b.writeInt(16); @@ -155,7 +156,7 @@ class LimitsTest { "tableSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.code()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(-1);//max stack b.writeU2(-1);//max locals b.writeInt(16); @@ -173,7 +174,7 @@ class LimitsTest { "tableSwitchMethod", MethodTypeDesc.of(ConstantDescs.CD_void), 0, mb -> ((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.code()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(-1);//max stack b.writeU2(-1);//max locals b.writeInt(20); diff --git a/test/jdk/jdk/classfile/LowAdaptTest.java b/test/jdk/jdk/classfile/LowAdaptTest.java index 46d033a8676..9fa2620913b 100644 --- a/test/jdk/jdk/classfile/LowAdaptTest.java +++ b/test/jdk/jdk/classfile/LowAdaptTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -39,11 +39,8 @@ import java.lang.classfile.AccessFlags; import java.lang.reflect.AccessFlag; import java.lang.classfile.ClassModel; import java.lang.classfile.ClassFile; -import java.lang.classfile.Opcode; -import java.lang.classfile.TypeKind; import helpers.ByteArrayClassLoader; import java.lang.classfile.attribute.SourceFileAttribute; -import jdk.internal.classfile.impl.DirectClassBuilder; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -75,7 +72,7 @@ class LowAdaptTest { byte[] clazz = cc.build(ClassDesc.of(test), cb -> { cb.withFlags(AccessFlag.PUBLIC); cb.with(SourceFileAttribute.of("/some/madeup/TestClass.java")); - cl.methods().forEach(m -> ((DirectClassBuilder) cb).withMethod(m)); + cl.methods().forEach(cb::with); cb.withMethod("doit", MethodTypeDesc.of(CD_int, CD_int), AccessFlags.ofMethod(AccessFlag.PUBLIC, AccessFlag.STATIC).flagsMask(), diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java index 84a5ded1610..d0943d2eee9 100644 --- a/test/jdk/jdk/classfile/VerifierSelfTest.java +++ b/test/jdk/jdk/classfile/VerifierSelfTest.java @@ -47,6 +47,8 @@ import java.lang.classfile.*; import java.lang.classfile.attribute.*; import java.lang.classfile.components.ClassPrinter; import java.lang.constant.ModuleDesc; + +import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; @@ -103,7 +105,7 @@ class VerifierSelfTest { var bytes = cc.build(ClassDesc.of("InvalidAttrLocationClass"), cb -> ((DirectClassBuilder)cb).writeAttribute(new UnboundAttribute.AdHocAttribute(Attributes.localVariableTable()) { @Override - public void writeBody(BufWriter b) { + public void writeBody(BufWriterImpl b) { b.writeU2(0); } })); diff --git a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java index a5598d1f242..d85b37aa3a3 100644 --- a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java +++ b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -70,8 +70,8 @@ public class AnnotationDefaultVerifier { private abstract class TestElementValue { public void testLength(TestResult testCase, AnnotationDefaultAttribute attr) { - BufWriter buf = new BufWriterImpl(ConstantPoolBuilder.of(), (ClassFileImpl) ClassFile.of()); - attr.defaultValue().writeTo(buf); + var buf = new BufWriterImpl(ConstantPoolBuilder.of(), (ClassFileImpl) ClassFile.of()); + AnnotationReader.writeAnnotationValue(buf, attr.defaultValue()); testCase.checkEquals(((BoundAttribute)attr).payloadLen(), buf.size(), "attribute_length"); }