mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
249 lines
11 KiB
Java
249 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2022, 2025, 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.attribute.BootstrapMethodsAttribute;
|
|
import java.lang.classfile.attribute.CodeAttribute;
|
|
import java.lang.classfile.attribute.UnknownAttribute;
|
|
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
|
import java.lang.classfile.constantpool.Utf8Entry;
|
|
|
|
/**
|
|
* Bidirectional mapper between the {@code class} file representation of an
|
|
* attribute and its API model. The attribute mapper identifies an attribute
|
|
* by its {@linkplain Attribute#attributeName name}, and is used to parse the
|
|
* {@code class} file representation into a model, and to write the model
|
|
* representation back to a {@code class} file.
|
|
* <p>
|
|
* {@link Attributes} defines the mappers for predefined attributes in the JVMS
|
|
* and certain conventional attributes. For other attributes (JVMS {@jvms
|
|
* 4.7.1}), users can define their own {@code AttributeMapper}; classes that
|
|
* model those attributes should extend {@link CustomAttribute}. To read those
|
|
* attributes, user-defined {@code AttributeMapper}s must be registered to the
|
|
* {@link ClassFile.AttributeMapperOption}.
|
|
*
|
|
* @param <A> the attribute type
|
|
* @see Attributes
|
|
* @see ClassFile.AttributeMapperOption
|
|
* @see java.lang.classfile.attribute
|
|
* @since 24
|
|
*/
|
|
public interface AttributeMapper<A extends Attribute<A>> {
|
|
|
|
/**
|
|
* Indicates the data dependency of the {@code class} file representation
|
|
* of an attribute. Whether an attribute can be bulk-copied by its binary
|
|
* representation to a new {@code class} file depends on if its data refers
|
|
* to other parts of its enclosing {@code class} file.
|
|
*
|
|
* @apiNote
|
|
* This dependency is called "stability" because it indicates the conditions
|
|
* for a {@code class} file attribute to be eligible for bulk-copying to
|
|
* another {@code class} file.
|
|
*
|
|
* @see AttributeMapper#stability()
|
|
* @since 24
|
|
*/
|
|
enum AttributeStability {
|
|
|
|
/**
|
|
* The attribute contains only standalone data, and has no reference to
|
|
* other parts of its enclosing {@code class} file, besides the name of
|
|
* the attribute. Thus, its contents can always be bulk-copied to
|
|
* another {@code class} file.
|
|
* <p>
|
|
* For example, a bit mask is standalone data.
|
|
*/
|
|
STATELESS,
|
|
|
|
/**
|
|
* In addition to standalone data, the attribute refers to the constant
|
|
* pool, including the {@link BootstrapMethodsAttribute BootstrapMethods}
|
|
* attribute, of its enclosing {@code class} file. Thus, it can be
|
|
* bulk-copied when the destination {@code class} file extends its
|
|
* constant pool from that of the original {@code class}. It must be
|
|
* expanded to translate constant pool references and rewritten when
|
|
* constant pool indices are not compatible.
|
|
* <p>
|
|
* For example, a {@link Utf8Entry} is a reference to the constant pool.
|
|
*
|
|
* @see ConstantPoolBuilder#of(ClassModel)
|
|
* @see ClassFile.ConstantPoolSharingOption
|
|
*/
|
|
CP_REFS,
|
|
|
|
/**
|
|
* In addition to standalone data and references to the constant pool,
|
|
* the attribute refers to positions into the {@code code} array of a
|
|
* {@link CodeAttribute Code} attribute. Thus, it can be bulked-copied
|
|
* when the {@code code} array is unchanged, which requires that the
|
|
* destination {@code class} file extends its constant pool from that of
|
|
* the original {@code class}. It must be expanded to translate {@link
|
|
* Label}s or constant pool references and rewritten if the {@code code}
|
|
* array is perturbed, including when constant pool indices are not
|
|
* compatible.
|
|
* <p>
|
|
* For example, a bci value, modeled by a {@link Label}, is a reference
|
|
* to a position in the {@code code} array.
|
|
*/
|
|
LABELS,
|
|
|
|
/**
|
|
* The attribute refers to structures not managed by the library (type
|
|
* variable lists, etc.). As a result, even when the attribute is
|
|
* expanded, those references may not be correctly translated, and the
|
|
* rewritten results may be incorrect.
|
|
* <p>
|
|
* If the attribute is read from a {@code class} file, {@link
|
|
* ClassFile.AttributesProcessingOption} determines whether to preserve
|
|
* or drop the attribute during transformation.
|
|
*
|
|
* @see ClassFile.AttributesProcessingOption#DROP_UNSTABLE_ATTRIBUTES
|
|
*/
|
|
UNSTABLE,
|
|
|
|
/**
|
|
* The attribute is completely unknown. As a result, expanding and
|
|
* rewriting is not possible, and any difference between the destination
|
|
* {@code class} file and its enclosing {@code class} file may make the
|
|
* attribute incorrect.
|
|
* <p>
|
|
* {@link ClassFile.AttributesProcessingOption} determines whether to
|
|
* preserve or drop the attribute during transformation.
|
|
*
|
|
* @see UnknownAttribute
|
|
* @see ClassFile.AttributesProcessingOption#DROP_UNSTABLE_ATTRIBUTES
|
|
* @see ClassFile.AttributesProcessingOption#DROP_UNKNOWN_ATTRIBUTES
|
|
*/
|
|
UNKNOWN
|
|
}
|
|
|
|
/**
|
|
* {@return the name of the attribute}
|
|
*/
|
|
String name();
|
|
|
|
/**
|
|
* Creates an {@link Attribute} instance from a {@code class} file for the
|
|
* Class-File API.
|
|
* <p>
|
|
* This method is called by the Class-File API to support reading of
|
|
* attributes. Users should never call this method.
|
|
* <p>
|
|
* The Class-File API makes these promises about the call to this method:
|
|
* <ul>
|
|
* <li>The {@link Utf8Entry} for the name of the attribute is accessible
|
|
* with {@code cf.readEntry(pos - 6, Utf8Entry.class)}, and is validated;
|
|
* <li>The length of the attribute is accessible with {@code cf.readInt(pos
|
|
* - 4)}, and is validated to be positive and not beyond the length of the
|
|
* {@code class} file;
|
|
* <li>The {@link AttributedElement} attribute access functionalities on the
|
|
* {@code enclosing} model may not be accessed when this method is called,
|
|
* but can be accessed later by the returned attribute when it is accessible
|
|
* to users.
|
|
* </ul>
|
|
* <p>
|
|
* The returned {@code Attribute} must fulfill these requirements:
|
|
* <ul>
|
|
* <li>{@link Attribute#attributeMapper()} returns this mapper;
|
|
* <li>{@link Attribute#attributeName()} returns the attribute name in the
|
|
* {@code class} file.
|
|
* </ul>
|
|
*
|
|
* @apiNote
|
|
* Implementations of this method should perform minimal work to return an
|
|
* attribute, as this method is called even if the resulting attribute is
|
|
* never used. In particular, the implementation should avoid checking the
|
|
* validity of the attribute {@code class} file data or performing actions
|
|
* that may throw exceptions.
|
|
*
|
|
* @param enclosing the structure in which this attribute appears
|
|
* @param cf provides access to the {@code class} file to read from
|
|
* @param pos the offset into the {@code class} file at which the contents
|
|
* of the attribute starts
|
|
* @return the read attribute
|
|
*/
|
|
A readAttribute(AttributedElement enclosing, ClassReader cf, int pos);
|
|
|
|
/**
|
|
* Writes an {@link Attribute} instance to a {@code class} file for the
|
|
* Class-File API.
|
|
* <p>
|
|
* This method is called by the Class-File API to support writing of
|
|
* attributes. Users should never call this method.
|
|
* <p>
|
|
* The Class-File API makes these promises about the call to this method:
|
|
* <ul>
|
|
* <li>{@link Attribute#attributeMapper() attr.attributeMapper()} returns
|
|
* this mapper;
|
|
* <li>The {@code buf} may already have data written, that its {@link
|
|
* BufWriter#size() size} may not be {@code 0}.
|
|
* </ul>
|
|
* <p>
|
|
* The {@code class} file writing must fulfill these requirements:
|
|
* <ul>
|
|
* <li>The attribute name {@code u2} and attribute length {@code u4} must
|
|
* be written to the {@code buf};
|
|
* <li>{@link Attribute#attributeName() attr.attributeName()} is written as
|
|
* if with {@code buf.writeIndex(attr.attributeName())};
|
|
* <li>The attribute length is the length, in bytes, of attribute contents
|
|
* written to the {@code buf}, not including the 6 bytes used by the name
|
|
* and the length;
|
|
* <li>If any information in the API model of the attribute, {@code attr},
|
|
* cannot be represented in the {@code class} file format of the attribute,
|
|
* an {@link IllegalArgumentException} is thrown.
|
|
* </ul>
|
|
*
|
|
* @apiNote
|
|
* {@link BufWriter#patchInt} can be used to update the attribute length
|
|
* after the attribute contents are written to the {@code buf}.
|
|
*
|
|
* @param buf the {@link BufWriter} to which the attribute should be written
|
|
* @param attr the attribute to write
|
|
* @throws IllegalArgumentException if some data in the API model of the
|
|
* attribute is invalid for the {@code class} file format
|
|
*/
|
|
void writeAttribute(BufWriter buf, A attr);
|
|
|
|
/**
|
|
* {@return whether this attribute may appear more than once in one
|
|
* structure}
|
|
* <p>
|
|
* If an attribute does not allow multiple instances in one structure,
|
|
* can be supplied to a {@link ClassFileBuilder}, and multiple instances of
|
|
* the attribute are supplied to the builder, the last supplied attribute
|
|
* appears on the built structure.
|
|
*
|
|
* @implSpec The default implementation returns {@code false}.
|
|
*/
|
|
default boolean allowMultiple() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* {@return the data dependency of this attribute on the {@code class} file}
|
|
*/
|
|
AttributeStability stability();
|
|
}
|