8335939: Hide element writing across the ClassFile API

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-07-23 12:11:47 +00:00
parent e83b4b236e
commit a2a236f904
50 changed files with 263 additions and 360 deletions

View File

@ -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<Annotation>
permits TypeAnnotation, AnnotationImpl {
/**

View File

@ -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<AnnotationElement>
permits AnnotationImpl.AnnotationElementImpl {
/**

View File

@ -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<AnnotationValue>
public sealed interface AnnotationValue
permits AnnotationValue.OfAnnotation, AnnotationValue.OfArray,
AnnotationValue.OfConstant, AnnotationValue.OfClass,
AnnotationValue.OfEnum {

View File

@ -80,7 +80,7 @@ import jdk.internal.javac.PreviewFeature;
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface Attribute<A extends Attribute<A>>
extends WritableElement<A>
extends ClassFileElement
permits AnnotationDefaultAttribute, BootstrapMethodsAttribute,
CharacterRangeTableAttribute, CodeAttribute, CompilationIDAttribute,
ConstantValueAttribute, DeprecatedAttribute, EnclosingMethodAttribute,

View File

@ -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<BootstrapMethodEntry>
permits BootstrapMethodEntryImpl {
/**

View File

@ -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 <T> the type of entity
*/
<T extends WritableElement<?>> void writeList(List<T> 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<? extends PoolEntry> 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);
}

View File

@ -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 {
}

View File

@ -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);
}

View File

@ -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<T extends CustomAttribute<T>>
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());

View File

@ -42,7 +42,7 @@ import jdk.internal.javac.PreviewFeature;
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface FieldModel
extends WritableElement<FieldModel>, CompoundElement<FieldElement>, AttributedElement, ClassElement
extends CompoundElement<FieldElement>, AttributedElement, ClassElement
permits BufferedFieldBuilder.Model, FieldImpl {
/** {@return the access flags} */

View File

@ -42,7 +42,7 @@ import jdk.internal.javac.PreviewFeature;
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface MethodModel
extends WritableElement<MethodModel>, CompoundElement<MethodElement>, AttributedElement, ClassElement
extends CompoundElement<MethodElement>, AttributedElement, ClassElement
permits BufferedMethodBuilder.Model, MethodImpl {
/** {@return the access flags} */

View File

@ -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 <T> the type of the entity
*
* @sealedGraph
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface WritableElement<T> 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);
}

View File

@ -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<ConstantPool>
extends ConstantPool
permits SplitConstantPool, TemporaryConstantPool {
/**

View File

@ -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<PoolEntry>
public sealed interface PoolEntry
permits AnnotationConstantValueEntry, DynamicConstantPoolEntry,
LoadableConstantEntry, MemberRefEntry, ModuleEntry, NameAndTypeEntry,
PackageEntry {

View File

@ -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}
*

View File

@ -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}
*

View File

@ -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<T extends Attribute<T>>
@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<T extends Attribute<T>>
@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<T extends Attribute<T>>
@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<T extends Attribute<T>>
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<T extends Attribute<T>>
@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<T extends Attribute<T>>
@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<T extends Attribute<T>>
@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<T extends Attribute<T>>
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<T extends Attribute<T>>
@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<T extends Attribute<T>>
List<List<Annotation>> lists = attr.parameterAnnotations();
buf.writeU1(lists.size());
for (List<Annotation> list : lists)
buf.writeList(list);
AnnotationReader.writeAnnotations(buf, list);
}
}
@ -653,7 +657,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@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<T extends Attribute<T>>
@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<T extends Attribute<T>>
List<List<Annotation>> lists = attr.parameterAnnotations();
buf.writeU1(lists.size());
for (List<Annotation> list : lists)
buf.writeList(list);
AnnotationReader.writeAnnotations(buf, list);
}
}
@ -710,7 +714,7 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
@Override
protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
buf.writeList(attr.annotations());
AnnotationReader.writeAnnotations(buf, attr.annotations());
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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) {

View File

@ -35,7 +35,7 @@ import java.lang.classfile.CompoundElement;
public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
extends AbstractElement
implements CompoundElement<E>, AttributedElement
implements CompoundElement<E>, AttributedElement, Util.Writable
permits BufferedCodeBuilder.Model, BufferedFieldBuilder.Model, BufferedMethodBuilder.Model {
private final List<E> elements;
private List<Attribute<?>> attributes;

View File

@ -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<AnnotationElement> 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<AnnotationValue> values)
implements AnnotationValue.OfArray {
implements AnnotationValue.OfArray, Util.Writable {
public OfArrayImpl(List<AnnotationValue> 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);
}

View File

@ -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<Annotation> 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<? extends Annotation> 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);
}
}

View File

@ -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<Attribute<?>> 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) {

View File

@ -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());
}
}

View File

@ -48,7 +48,7 @@ import static java.lang.classfile.Attributes.*;
public abstract sealed class BoundAttribute<T extends Attribute<T>>
extends AbstractElement
implements Attribute<T> {
implements Attribute<T>, Util.Writable {
static final int NAME_AND_LENGTH_PREFIX = 6;
private final AttributeMapper<T> mapper;
@ -101,7 +101,7 @@ public abstract sealed class BoundAttribute<T extends Attribute<T>>
@Override
@SuppressWarnings("unchecked")
public void writeTo(BufWriter buf) {
public void writeTo(BufWriterImpl buf) {
if (!buf.canWriteDirect(classReader))
attributeMapper().writeAttribute(buf, (T) this);
else

View File

@ -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<T extends WritableElement<?>> void writeList(List<T> list) {
writeU2(list.size());
for (T t : list) {
t.writeTo(this);
}
}
@Override
public void writeListIndices(List<? extends PoolEntry> list) {
writeU2(list.size());
for (PoolEntry info : list) {
writeIndex(info);
}
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -321,12 +321,13 @@ public final class ClassReaderImpl
return containedClass;
}
boolean writeBootstrapMethods(BufWriter buf) {
boolean writeBootstrapMethods(BufWriterImpl buf) {
Optional<BootstrapMethodsAttribute> 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) {

View File

@ -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);
}

View File

@ -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<WritableElement<FieldModel>> fields = new ArrayList<>();
private final List<WritableElement<MethodModel>> methods = new ArrayList<>();
private final List<Util.Writable> fields = new ArrayList<>();
private final List<Util.Writable> methods = new ArrayList<>();
private ClassEntry superclassEntry;
private List<ClassEntry> 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<FieldModel> field) {
ClassBuilder withField(Util.Writable field) {
fields.add(field);
return this;
}
public ClassBuilder withMethod(WritableElement<MethodModel> 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()];

View File

@ -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<CodeAttribute, int[]> parentMap;
@ -100,7 +96,7 @@ public final class DirectCodeBuilder
allocLocal(TypeKind) bumps by nSlots
*/
public static Attribute<CodeAttribute> build(MethodInfo methodInfo,
public static UnboundAttribute<CodeAttribute> build(MethodInfo methodInfo,
Consumer<? super CodeBuilder> 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<CodeAttribute> content = null;
private UnboundAttribute<CodeAttribute> 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());
}

View File

@ -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<FieldModel>
implements TerminalFieldBuilder, WritableElement<FieldModel> {
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);

View File

@ -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<MethodModel>
implements TerminalMethodBuilder, WritableElement<MethodModel> {
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);

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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<BootstrapMethodsAttribute> a
UnboundAttribute<BootstrapMethodsAttribute> 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();
}

View File

@ -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);
}

View File

@ -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<? extends StackMapTableAttribute> 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);

View File

@ -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();
}
}

View File

@ -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<T extends Attribute<T>>
extends AbstractElement
implements Attribute<T> {
implements Attribute<T>, Util.Writable {
protected final AttributeMapper<T> mapper;
public UnboundAttribute(AttributeMapper<T> mapper) {
@ -114,7 +113,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
@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<T extends Attribute<T>>
public record UnboundTypeAnnotation(TargetInfo targetInfo,
List<TypePathComponent> targetPath,
Utf8Entry className,
List<AnnotationElement> elements) implements TypeAnnotation {
List<AnnotationElement> elements) implements TypeAnnotation, Util.Writable {
public UnboundTypeAnnotation(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry className, List<AnnotationElement> elements) {
@ -769,8 +768,8 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
}
@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<T extends Attribute<T>>
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<T extends Attribute<T>>
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();

View File

@ -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 <T> void writeAttribute(BufWriterImpl writer, Attribute<?> attr) {
if (attr instanceof CustomAttribute<?> ca) {
var mapper = (AttributeMapper<T>) 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<? extends Attribute<?>> list) {
buf.writeU2(list.size());
for (var e : list) {
writeAttribute(buf, e);
}
}
static void writeList(BufWriterImpl buf, List<Writable> 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<CodeAttribute>(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<? extends PoolEntry> 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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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<CodeAttribute>(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<CodeAttribute>(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<CodeAttribute>(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);

View File

@ -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(),

View File

@ -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<LocalVariableTableAttribute>(Attributes.localVariableTable()) {
@Override
public void writeBody(BufWriter b) {
public void writeBody(BufWriterImpl b) {
b.writeU2(0);
}
}));

View File

@ -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");
}