8294982: Implementation of Classfile API

Reviewed-by: ihse, psandoz, mcimadamore
This commit is contained in:
Adam Sotona 2023-03-09 15:23:03 +00:00
parent 1e9942aa11
commit 4655b790d0
322 changed files with 52932 additions and 4 deletions

View File

@ -592,7 +592,16 @@ define SetupRunMicroTestBody
endif
# Set library path for native dependencies
$1_JMH_JVM_ARGS := -Djava.library.path=$$(TEST_IMAGE_DIR)/micro/native
$1_JMH_JVM_ARGS := -Djava.library.path=$$(TEST_IMAGE_DIR)/micro/native \
--add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
--add-exports java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.attribute=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.constantpool=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.instruction=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.java.lang.constant=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.components=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.impl=ALL-UNNAMED
ifneq ($$(MICRO_VM_OPTIONS)$$(MICRO_JAVA_OPTIONS), )
$1_JMH_JVM_ARGS += $$(MICRO_VM_OPTIONS) $$(MICRO_JAVA_OPTIONS)

View File

@ -25,7 +25,9 @@
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
JAVAC_FLAGS += -XDstringConcat=inline
JAVAC_FLAGS += -XDstringConcat=inline \
--enable-preview
DISABLED_WARNINGS_java += preview
COPY += .icu .dat .spp .nrm content-types.properties \
hijrah-config-Hijrah-umalqura_islamic-umalqura.properties
CLEAN += intrinsic.properties
@ -33,7 +35,9 @@ CLEAN += intrinsic.properties
EXCLUDE_FILES += \
$(TOPDIR)/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
EXCLUDES += java/lang/doc-files
EXCLUDES += java/lang/doc-files \
jdk/internal/classfile/snippet-files \
jdk/internal/classfile/components/snippet-files
# Exclude BreakIterator classes that are just used in compile process to generate
# data files and shouldn't go in the product

View File

@ -96,6 +96,15 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
BIN := $(MICROBENCHMARK_CLASSES), \
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
--add-exports java.base/sun.invoke.util=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.attribute=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.constantpool=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.instruction=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.java.lang.constant=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.components=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.impl=ALL-UNNAMED \
--add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
--add-exports java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED \
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
--enable-preview, \
JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management \

View File

@ -0,0 +1,112 @@
/*
* 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 jdk.internal.classfile;
import java.util.Set;
import jdk.internal.classfile.impl.AccessFlagsImpl;
import java.lang.reflect.AccessFlag;
/**
* Models the access flags for a class, method, or field. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing
* the corresponding model type.
*/
public sealed interface AccessFlags
extends ClassElement, MethodElement, FieldElement
permits AccessFlagsImpl {
/**
* {@return the access flags, as a bit mask}
*/
int flagsMask();
/**
* {@return the access flags}
*/
Set<AccessFlag> flags();
/**
* {@return whether the specified flag is present} The specified flag
* should be a valid flag for the classfile location associated with this
* element otherwise false is returned.
* @param flag the flag to test
*/
boolean has(AccessFlag flag);
/**
* {@return the classfile location for this element, which is either class,
* method, or field}
*/
AccessFlag.Location location();
/**
* {@return an {@linkplain AccessFlags} for a class}
* @param mask the flags to be set, as a bit mask
*/
static AccessFlags ofClass(int mask) {
return new AccessFlagsImpl(AccessFlag.Location.CLASS, mask);
}
/**
* {@return an {@linkplain AccessFlags} for a class}
* @param flags the flags to be set
*/
static AccessFlags ofClass(AccessFlag... flags) {
return new AccessFlagsImpl(AccessFlag.Location.CLASS, flags);
}
/**
* {@return an {@linkplain AccessFlags} for a field}
* @param mask the flags to be set, as a bit mask
*/
static AccessFlags ofField(int mask) {
return new AccessFlagsImpl(AccessFlag.Location.FIELD, mask);
}
/**
* {@return an {@linkplain AccessFlags} for a field}
* @param flags the flags to be set
*/
static AccessFlags ofField(AccessFlag... flags) {
return new AccessFlagsImpl(AccessFlag.Location.FIELD, flags);
}
/**
* {@return an {@linkplain AccessFlags} for a method}
* @param mask the flags to be set, as a bit mask
*/
static AccessFlags ofMethod(int mask) {
return new AccessFlagsImpl(AccessFlag.Location.METHOD, mask);
}
/**
* {@return an {@linkplain AccessFlags} for a method}
* @param flags the flags to be set
*/
static AccessFlags ofMethod(AccessFlag... flags) {
return new AccessFlagsImpl(AccessFlag.Location.METHOD, flags);
}
}

View File

@ -0,0 +1,108 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.AnnotationImpl;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import java.lang.constant.ClassDesc;
import java.util.List;
/**
* Models an annotation on a declaration.
*
* @see AnnotationElement
* @see AnnotationValue
* @see RuntimeVisibleAnnotationsAttribute
* @see RuntimeInvisibleAnnotationsAttribute
* @see RuntimeVisibleParameterAnnotationsAttribute
* @see RuntimeInvisibleParameterAnnotationsAttribute
*/
public sealed interface Annotation
extends WritableElement<Annotation>
permits TypeAnnotation, AnnotationImpl {
/**
* {@return the class of the annotation}
*/
Utf8Entry className();
/**
* {@return the class of the annotation, as a symbolic descriptor}
*/
default ClassDesc classSymbol() {
return ClassDesc.ofDescriptor(className().stringValue());
}
/**
* {@return the elements of the annotation}
*/
List<AnnotationElement> elements();
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
*/
static Annotation of(Utf8Entry annotationClass,
List<AnnotationElement> elements) {
return new AnnotationImpl(annotationClass, elements);
}
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
*/
static Annotation of(Utf8Entry annotationClass,
AnnotationElement... elements) {
return of(annotationClass, List.of(elements));
}
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
*/
static Annotation of(ClassDesc annotationClass,
List<AnnotationElement> elements) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(annotationClass.descriptorString()), elements);
}
/**
* {@return an annotation}
* @param annotationClass the class of the annotation
* @param elements the elements of the annotation
*/
static Annotation of(ClassDesc annotationClass,
AnnotationElement... elements) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(annotationClass.descriptorString()), elements);
}
}

View File

@ -0,0 +1,193 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.AnnotationImpl;
import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* Models a key-value pair of an annotation.
*
* @see Annotation
* @see AnnotationValue
*/
public sealed interface AnnotationElement
extends WritableElement<AnnotationElement>
permits AnnotationImpl.AnnotationElementImpl {
/**
* {@return the element name}
*/
Utf8Entry name();
/**
* {@return the element value}
*/
AnnotationValue value();
/**
* {@return an annotation key-value pair}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement of(Utf8Entry name,
AnnotationValue value) {
return new AnnotationImpl.AnnotationElementImpl(name, value);
}
/**
* {@return an annotation key-value pair}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement of(String name,
AnnotationValue value) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(name), value);
}
/**
* {@return an annotation key-value pair for a class-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofClass(String name,
ClassDesc value) {
return of(name, AnnotationValue.ofClass(value));
}
/**
* {@return an annotation key-value pair for a string-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofString(String name,
String value) {
return of(name, AnnotationValue.ofString(value));
}
/**
* {@return an annotation key-value pair for a long-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofLong(String name,
long value) {
return of(name, AnnotationValue.ofLong(value));
}
/**
* {@return an annotation key-value pair for an int-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofInt(String name,
int value) {
return of(name, AnnotationValue.ofInt(value));
}
/**
* {@return an annotation key-value pair for a char-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofChar(String name,
char value) {
return of(name, AnnotationValue.ofChar(value));
}
/**
* {@return an annotation key-value pair for a short-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofShort(String name,
short value) {
return of(name, AnnotationValue.ofShort(value));
}
/**
* {@return an annotation key-value pair for a byte-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofByte(String name,
byte value) {
return of(name, AnnotationValue.ofByte(value));
}
/**
* {@return an annotation key-value pair for a boolean-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofBoolean(String name,
boolean value) {
return of(name, AnnotationValue.ofBoolean(value));
}
/**
* {@return an annotation key-value pair for a double-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofDouble(String name,
double value) {
return of(name, AnnotationValue.ofDouble(value));
}
/**
* {@return an annotation key-value pair for a float-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofFloat(String name,
float value) {
return of(name, AnnotationValue.ofFloat(value));
}
/**
* {@return an annotation key-value pair for an annotation-valued annotation}
* @param name the name of the key
* @param value the associated value
*/
static AnnotationElement ofAnnotation(String name,
Annotation value) {
return of(name, AnnotationValue.ofAnnotation(value));
}
/**
* {@return an annotation key-value pair for an array-valued annotation}
* @param name the name of the key
* @param values the associated values
*/
static AnnotationElement ofArray(String name,
AnnotationValue... values) {
return of(name, AnnotationValue.ofArray(values));
}
}

View File

@ -0,0 +1,467 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.constantpool.AnnotationConstantValueEntry;
import jdk.internal.classfile.constantpool.DoubleEntry;
import jdk.internal.classfile.constantpool.FloatEntry;
import jdk.internal.classfile.constantpool.IntegerEntry;
import jdk.internal.classfile.constantpool.LongEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.AnnotationImpl;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDesc;
import java.util.ArrayList;
import java.util.List;
/**
* Models the value of a key-value pair of an annotation.
*
* @see Annotation
* @see AnnotationElement
*/
public sealed interface AnnotationValue extends WritableElement<AnnotationValue>
permits AnnotationValue.OfAnnotation, AnnotationValue.OfArray,
AnnotationValue.OfConstant, AnnotationValue.OfClass,
AnnotationValue.OfEnum {
/** Models an annotation-valued element */
sealed interface OfAnnotation extends AnnotationValue
permits AnnotationImpl.OfAnnotationImpl {
/** {@return the annotation} */
Annotation annotation();
}
/** Models an array-valued element */
sealed interface OfArray extends AnnotationValue
permits AnnotationImpl.OfArrayImpl {
/** {@return the values} */
List<AnnotationValue> values();
}
/** Models a constant-valued element */
sealed interface OfConstant extends AnnotationValue
permits AnnotationValue.OfString, AnnotationValue.OfDouble,
AnnotationValue.OfFloat, AnnotationValue.OfLong,
AnnotationValue.OfInteger, AnnotationValue.OfShort,
AnnotationValue.OfCharacter, AnnotationValue.OfByte,
AnnotationValue.OfBoolean, AnnotationImpl.OfConstantImpl {
/** {@return the constant} */
AnnotationConstantValueEntry constant();
/** {@return the constant} */
ConstantDesc constantValue();
}
/** Models a constant-valued element */
sealed interface OfString extends AnnotationValue.OfConstant
permits AnnotationImpl.OfStringImpl {
/** {@return the constant} */
String stringValue();
}
/** Models a constant-valued element */
sealed interface OfDouble extends AnnotationValue.OfConstant
permits AnnotationImpl.OfDoubleImpl {
/** {@return the constant} */
double doubleValue();
}
/** Models a constant-valued element */
sealed interface OfFloat extends AnnotationValue.OfConstant
permits AnnotationImpl.OfFloatImpl {
/** {@return the constant} */
float floatValue();
}
/** Models a constant-valued element */
sealed interface OfLong extends AnnotationValue.OfConstant
permits AnnotationImpl.OfLongImpl {
/** {@return the constant} */
long longValue();
}
/** Models a constant-valued element */
sealed interface OfInteger extends AnnotationValue.OfConstant
permits AnnotationImpl.OfIntegerImpl {
/** {@return the constant} */
int intValue();
}
/** Models a constant-valued element */
sealed interface OfShort extends AnnotationValue.OfConstant
permits AnnotationImpl.OfShortImpl {
/** {@return the constant} */
short shortValue();
}
/** Models a constant-valued element */
sealed interface OfCharacter extends AnnotationValue.OfConstant
permits AnnotationImpl.OfCharacterImpl {
/** {@return the constant} */
char charValue();
}
/** Models a constant-valued element */
sealed interface OfByte extends AnnotationValue.OfConstant
permits AnnotationImpl.OfByteImpl {
/** {@return the constant} */
byte byteValue();
}
/** Models a constant-valued element */
sealed interface OfBoolean extends AnnotationValue.OfConstant
permits AnnotationImpl.OfBooleanImpl {
/** {@return the constant} */
boolean booleanValue();
}
/** Models a class-valued element */
sealed interface OfClass extends AnnotationValue
permits AnnotationImpl.OfClassImpl {
/** {@return the class name} */
Utf8Entry className();
/** {@return the class symbol} */
default ClassDesc classSymbol() {
return ClassDesc.ofDescriptor(className().stringValue());
}
}
/** Models an enum-valued element */
sealed interface OfEnum extends AnnotationValue
permits AnnotationImpl.OfEnumImpl {
/** {@return the enum class name} */
Utf8Entry className();
/** {@return the enum class symbol} */
default ClassDesc classSymbol() {
return ClassDesc.ofDescriptor(className().stringValue());
}
/** {@return the enum constant name} */
Utf8Entry constantName();
}
/**
* @return the tag character for this type as per {@jvms 4.7.16.1}
*/
char tag();
/**
* {@return an annotation element for a enum-valued element}
* @param className the name of the enum class
* @param constantName the name of the enum constant
*/
static OfEnum ofEnum(Utf8Entry className,
Utf8Entry constantName) {
return new AnnotationImpl.OfEnumImpl(className, constantName);
}
/**
* {@return an annotation element for a enum-valued element}
* @param className the name of the enum class
* @param constantName the name of the enum constant
*/
static OfEnum ofEnum(ClassDesc className, String constantName) {
return ofEnum(TemporaryConstantPool.INSTANCE.utf8Entry(className.descriptorString()),
TemporaryConstantPool.INSTANCE.utf8Entry(constantName));
}
/**
* {@return an annotation element for a class-valued element}
* @param className the name of the enum class
*/
static OfClass ofClass(Utf8Entry className) {
return new AnnotationImpl.OfClassImpl(className);
}
/**
* {@return an annotation element for a class-valued element}
* @param className the name of the enum class
*/
static OfClass ofClass(ClassDesc className) {
return ofClass(TemporaryConstantPool.INSTANCE.utf8Entry(className.descriptorString()));
}
/**
* {@return an annotation element for a string-valued element}
* @param value the string
*/
static OfConstant ofString(Utf8Entry value) {
return new AnnotationImpl.OfStringImpl(value);
}
/**
* {@return an annotation element for a string-valued element}
* @param value the string
*/
static OfConstant ofString(String value) {
return ofString(TemporaryConstantPool.INSTANCE.utf8Entry(value));
}
/**
* {@return an annotation element for a double-valued element}
* @param value the double value
*/
static OfConstant ofDouble(DoubleEntry value) {
return new AnnotationImpl.OfDoubleImpl(value);
}
/**
* {@return an annotation element for a double-valued element}
* @param value the double value
*/
static OfConstant ofDouble(double value) {
return ofDouble(TemporaryConstantPool.INSTANCE.doubleEntry(value));
}
/**
* {@return an annotation element for a float-valued element}
* @param value the float value
*/
static OfConstant ofFloat(FloatEntry value) {
return new AnnotationImpl.OfFloatImpl(value);
}
/**
* {@return an annotation element for a float-valued element}
* @param value the float value
*/
static OfConstant ofFloat(float value) {
return ofFloat(TemporaryConstantPool.INSTANCE.floatEntry(value));
}
/**
* {@return an annotation element for a long-valued element}
* @param value the long value
*/
static OfConstant ofLong(LongEntry value) {
return new AnnotationImpl.OfLongImpl(value);
}
/**
* {@return an annotation element for a long-valued element}
* @param value the long value
*/
static OfConstant ofLong(long value) {
return ofLong(TemporaryConstantPool.INSTANCE.longEntry(value));
}
/**
* {@return an annotation element for an int-valued element}
* @param value the int value
*/
static OfConstant ofInt(IntegerEntry value) {
return new AnnotationImpl.OfIntegerImpl(value);
}
/**
* {@return an annotation element for an int-valued element}
* @param value the int value
*/
static OfConstant ofInt(int value) {
return ofInt(TemporaryConstantPool.INSTANCE.intEntry(value));
}
/**
* {@return an annotation element for a short-valued element}
* @param value the short value
*/
static OfConstant ofShort(IntegerEntry value) {
return new AnnotationImpl.OfShortImpl(value);
}
/**
* {@return an annotation element for a short-valued element}
* @param value the short value
*/
static OfConstant ofShort(short value) {
return ofShort(TemporaryConstantPool.INSTANCE.intEntry(value));
}
/**
* {@return an annotation element for a char-valued element}
* @param value the char value
*/
static OfConstant ofChar(IntegerEntry value) {
return new AnnotationImpl.OfCharacterImpl(value);
}
/**
* {@return an annotation element for a char-valued element}
* @param value the char value
*/
static OfConstant ofChar(char value) {
return ofChar(TemporaryConstantPool.INSTANCE.intEntry(value));
}
/**
* {@return an annotation element for a byte-valued element}
* @param value the byte value
*/
static OfConstant ofByte(IntegerEntry value) {
return new AnnotationImpl.OfByteImpl(value);
}
/**
* {@return an annotation element for a byte-valued element}
* @param value the byte value
*/
static OfConstant ofByte(byte value) {
return ofByte(TemporaryConstantPool.INSTANCE.intEntry(value));
}
/**
* {@return an annotation element for a boolean-valued element}
* @param value the boolean value
*/
static OfConstant ofBoolean(IntegerEntry value) {
return new AnnotationImpl.OfBooleanImpl(value);
}
/**
* {@return an annotation element for a boolean-valued element}
* @param value the boolean value
*/
static OfConstant ofBoolean(boolean value) {
int i = value ? 1 : 0;
return ofBoolean(TemporaryConstantPool.INSTANCE.intEntry(i));
}
/**
* {@return an annotation element for an annotation-valued element}
* @param value the annotation
*/
static OfAnnotation ofAnnotation(Annotation value) {
return new AnnotationImpl.OfAnnotationImpl(value);
}
/**
* {@return an annotation element for an array-valued element}
* @param values the values
*/
static OfArray ofArray(List<AnnotationValue> values) {
return new AnnotationImpl.OfArrayImpl(values);
}
/**
* {@return an annotation element for an array-valued element}
* @param values the values
*/
static OfArray ofArray(AnnotationValue... values) {
return ofArray(List.of(values));
}
/**
* {@return an annotation element} The {@code value} parameter must be
* a primitive, a String, a ClassDesc, an enum constant, or an array of
* one of these.
*
* @param value the annotation value
*/
static AnnotationValue of(Object value) {
if (value instanceof String s) {
return ofString(s);
} else if (value instanceof Byte b) {
return ofByte(b);
} else if (value instanceof Boolean b) {
return ofBoolean(b);
} else if (value instanceof Short s) {
return ofShort(s);
} else if (value instanceof Character c) {
return ofChar(c);
} else if (value instanceof Integer i) {
return ofInt(i);
} else if (value instanceof Long l) {
return ofLong(l);
} else if (value instanceof Float f) {
return ofFloat(f);
} else if (value instanceof Double d) {
return ofDouble(d);
} else if (value instanceof ClassDesc clsDesc) {
return ofClass(clsDesc);
} else if (value instanceof byte[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofByte(el));
}
return ofArray(els);
} else if (value instanceof boolean[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofBoolean(el));
}
return ofArray(els);
} else if (value instanceof short[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofShort(el));
}
return ofArray(els);
} else if (value instanceof char[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofChar(el));
}
return ofArray(els);
} else if (value instanceof int[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofInt(el));
}
return ofArray(els);
} else if (value instanceof long[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofLong(el));
}
return ofArray(els);
} else if (value instanceof float[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofFloat(el));
}
return ofArray(els);
} else if (value instanceof double[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(ofDouble(el));
}
return ofArray(els);
} else if (value instanceof Object[] arr) {
var els = new ArrayList<AnnotationValue>(arr.length);
for (var el : arr) {
els.add(of(el));
}
return ofArray(els);
} else if (value instanceof Enum<?> e) {
return ofEnum(ClassDesc.ofDescriptor(e.getDeclaringClass().descriptorString()), e.name());
}
throw new IllegalArgumentException("Illegal annotation constant value type " + (value == null ? null : value.getClass()));
}
}

View File

@ -0,0 +1,103 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.AnnotationDefaultAttribute;
import jdk.internal.classfile.attribute.BootstrapMethodsAttribute;
import jdk.internal.classfile.attribute.CharacterRangeTableAttribute;
import jdk.internal.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.attribute.CompilationIDAttribute;
import jdk.internal.classfile.attribute.ConstantValueAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.EnclosingMethodAttribute;
import jdk.internal.classfile.attribute.ExceptionsAttribute;
import jdk.internal.classfile.attribute.InnerClassesAttribute;
import jdk.internal.classfile.attribute.LineNumberTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTypeTableAttribute;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.ModuleHashesAttribute;
import jdk.internal.classfile.attribute.ModuleMainClassAttribute;
import jdk.internal.classfile.attribute.ModulePackagesAttribute;
import jdk.internal.classfile.attribute.ModuleResolutionAttribute;
import jdk.internal.classfile.attribute.ModuleTargetAttribute;
import jdk.internal.classfile.attribute.NestHostAttribute;
import jdk.internal.classfile.attribute.NestMembersAttribute;
import jdk.internal.classfile.attribute.PermittedSubclassesAttribute;
import jdk.internal.classfile.attribute.RecordAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.SignatureAttribute;
import jdk.internal.classfile.attribute.SourceDebugExtensionAttribute;
import jdk.internal.classfile.attribute.SourceFileAttribute;
import jdk.internal.classfile.attribute.SourceIDAttribute;
import jdk.internal.classfile.attribute.StackMapTableAttribute;
import jdk.internal.classfile.attribute.SyntheticAttribute;
import jdk.internal.classfile.attribute.UnknownAttribute;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a classfile attribute {@jvms 4.7}. Many, though not all, subtypes of
* {@linkplain Attribute} will implement {@link ClassElement}, {@link
* MethodElement}, {@link FieldElement}, or {@link CodeElement}; attributes that
* are also elements will be delivered when traversing the elements of the
* corresponding model type. Additionally, all attributes are accessible
* directly from the corresponding model type through {@link
* AttributedElement#findAttribute(AttributeMapper)}.
*/
public sealed interface Attribute<A extends Attribute<A>>
extends WritableElement<A>
permits AnnotationDefaultAttribute, BootstrapMethodsAttribute,
CharacterRangeTableAttribute, CodeAttribute, CompilationIDAttribute,
ConstantValueAttribute, DeprecatedAttribute, EnclosingMethodAttribute,
ExceptionsAttribute, InnerClassesAttribute, LineNumberTableAttribute,
LocalVariableTableAttribute, LocalVariableTypeTableAttribute,
MethodParametersAttribute, ModuleAttribute, ModuleHashesAttribute,
ModuleMainClassAttribute, ModulePackagesAttribute, ModuleResolutionAttribute,
ModuleTargetAttribute, NestHostAttribute, NestMembersAttribute,
PermittedSubclassesAttribute,
RecordAttribute, RuntimeInvisibleAnnotationsAttribute,
RuntimeInvisibleParameterAnnotationsAttribute, RuntimeInvisibleTypeAnnotationsAttribute,
RuntimeVisibleAnnotationsAttribute, RuntimeVisibleParameterAnnotationsAttribute,
RuntimeVisibleTypeAnnotationsAttribute, SignatureAttribute,
SourceDebugExtensionAttribute, SourceFileAttribute, SourceIDAttribute,
StackMapTableAttribute, SyntheticAttribute,
UnknownAttribute, BoundAttribute, UnboundAttribute {
/**
* {@return the name of the attribute}
*/
String attributeName();
/**
* {@return the {@link AttributeMapper} associated with this attribute}
*/
AttributeMapper<A> attributeMapper();
}

View File

@ -0,0 +1,77 @@
/*
* 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 jdk.internal.classfile;
/**
* Bidirectional mapper between the classfile representation of an attribute and
* how that attribute is modeled in the API. The attribute mapper is used
* to parse the classfile representation into a model, and to write the model
* representation back to a classfile. For each standard attribute, there is a
* predefined attribute mapper defined in {@link Attributes}. For nonstandard
* attributes, clients can define their own {@linkplain AttributeMapper}.
* Classes that model nonstandard attributes should extend {@link
* CustomAttribute}.
*/
public interface AttributeMapper<A> {
/**
* {@return the name of the attribute}
*/
String name();
/**
* Create an {@link Attribute} instance from a classfile.
*
* @param enclosing The class, method, field, or code attribute in which
* this attribute appears
* @param cf The {@link ClassReader} describing the classfile to read from
* @param pos The offset into the classfile at which the attribute starts
* @return the new attribute
*/
A readAttribute(AttributedElement enclosing, ClassReader cf, int pos);
/**
* Write an {@link Attribute} instance to a classfile.
*
* @param buf The {@link BufWriter} to which the attribute should be written
* @param attr The attribute to write
*/
void writeAttribute(BufWriter buf, A attr);
/**
* {@return The earliest classfile version for which this attribute is
* applicable}
*/
default int validSince() {
return Classfile.JAVA_1_VERSION;
}
/**
* {@return whether this attribute may appear more than once in a given location}
*/
default boolean allowMultiple() {
return false;
}
}

View File

@ -0,0 +1,83 @@
/*
* 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 jdk.internal.classfile;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import jdk.internal.classfile.attribute.RecordComponentInfo;
import jdk.internal.classfile.impl.AbstractUnboundModel;
/**
* A {@link ClassfileElement} describing an entity that has attributes, such
* as a class, field, method, code attribute, or record component.
*/
public sealed interface AttributedElement extends ClassfileElement
permits ClassModel, CodeModel, FieldModel, MethodModel,
RecordComponentInfo, AbstractUnboundModel {
/**
* {@return the attributes of this element}
*/
List<Attribute<?>> attributes();
/**
* Finds an attribute by name.
* @param attr the attribute mapper
* @param <T> the type of the attribute
* @return the attribute, or an empty {@linkplain Optional} if the attribute
* is not present
*/
default <T extends Attribute<T>> Optional<T> findAttribute(AttributeMapper<T> attr) {
for (Attribute<?> la : attributes()) {
if (la.attributeMapper() == attr) {
@SuppressWarnings("unchecked")
var res = Optional.of((T) la);
return res;
}
}
return Optional.empty();
}
/**
* Finds one or more attributes by name.
* @param attr the attribute mapper
* @param <T> the type of the attribute
* @return the attributes, or an empty {@linkplain List} if the attribute
* is not present
*/
default <T extends Attribute<T>> List<T> findAttributes(AttributeMapper<T> attr) {
var list = new ArrayList<T>();
for (var a : attributes()) {
if (a.attributeMapper() == attr) {
@SuppressWarnings("unchecked")
T t = (T)a;
list.add(t);
}
}
return list;
}
}

View File

@ -0,0 +1,786 @@
/*
* 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 jdk.internal.classfile;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.internal.classfile.attribute.AnnotationDefaultAttribute;
import jdk.internal.classfile.attribute.BootstrapMethodsAttribute;
import jdk.internal.classfile.attribute.CharacterRangeInfo;
import jdk.internal.classfile.attribute.CharacterRangeTableAttribute;
import jdk.internal.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.attribute.CompilationIDAttribute;
import jdk.internal.classfile.attribute.ConstantValueAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.EnclosingMethodAttribute;
import jdk.internal.classfile.attribute.ExceptionsAttribute;
import jdk.internal.classfile.attribute.InnerClassInfo;
import jdk.internal.classfile.attribute.InnerClassesAttribute;
import jdk.internal.classfile.attribute.LineNumberInfo;
import jdk.internal.classfile.attribute.LineNumberTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableInfo;
import jdk.internal.classfile.attribute.LocalVariableTableAttribute;
import jdk.internal.classfile.attribute.LocalVariableTypeInfo;
import jdk.internal.classfile.attribute.LocalVariableTypeTableAttribute;
import jdk.internal.classfile.attribute.MethodParameterInfo;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.ModuleExportInfo;
import jdk.internal.classfile.attribute.ModuleHashInfo;
import jdk.internal.classfile.attribute.ModuleHashesAttribute;
import jdk.internal.classfile.attribute.ModuleMainClassAttribute;
import jdk.internal.classfile.attribute.ModuleOpenInfo;
import jdk.internal.classfile.attribute.ModulePackagesAttribute;
import jdk.internal.classfile.attribute.ModuleProvideInfo;
import jdk.internal.classfile.attribute.ModuleRequireInfo;
import jdk.internal.classfile.attribute.ModuleResolutionAttribute;
import jdk.internal.classfile.attribute.ModuleTargetAttribute;
import jdk.internal.classfile.attribute.NestHostAttribute;
import jdk.internal.classfile.attribute.NestMembersAttribute;
import jdk.internal.classfile.attribute.PermittedSubclassesAttribute;
import jdk.internal.classfile.attribute.RecordAttribute;
import jdk.internal.classfile.attribute.RecordComponentInfo;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.SignatureAttribute;
import jdk.internal.classfile.attribute.SourceDebugExtensionAttribute;
import jdk.internal.classfile.attribute.SourceFileAttribute;
import jdk.internal.classfile.attribute.SourceIDAttribute;
import jdk.internal.classfile.attribute.StackMapTableAttribute;
import jdk.internal.classfile.attribute.SyntheticAttribute;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.AbstractAttributeMapper;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.CodeImpl;
import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.classfile.impl.StackMapDecoder;
/**
* Attribute mappers for standard classfile attributes.
*
* @see AttributeMapper
*/
public class Attributes {
public static final String NAME_ANNOTATION_DEFAULT = "AnnotationDefault";
public static final String NAME_BOOTSTRAP_METHODS = "BootstrapMethods";
public static final String NAME_CHARACTER_RANGE_TABLE = "CharacterRangeTable";
public static final String NAME_CODE = "Code";
public static final String NAME_COMPILATION_ID = "CompilationID";
public static final String NAME_CONSTANT_VALUE = "ConstantValue";
public static final String NAME_DEPRECATED = "Deprecated";
public static final String NAME_ENCLOSING_METHOD = "EnclosingMethod";
public static final String NAME_EXCEPTIONS = "Exceptions";
public static final String NAME_INNER_CLASSES = "InnerClasses";
public static final String NAME_LINE_NUMBER_TABLE = "LineNumberTable";
public static final String NAME_LOCAL_VARIABLE_TABLE = "LocalVariableTable";
public static final String NAME_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
public static final String NAME_METHOD_PARAMETERS = "MethodParameters";
public static final String NAME_MODULE = "Module";
public static final String NAME_MODULE_HASHES = "ModuleHashes";
public static final String NAME_MODULE_MAIN_CLASS = "ModuleMainClass";
public static final String NAME_MODULE_PACKAGES = "ModulePackages";
public static final String NAME_MODULE_RESOLUTION = "ModuleResolution";
public static final String NAME_MODULE_TARGET = "ModuleTarget";
public static final String NAME_NEST_HOST = "NestHost";
public static final String NAME_NEST_MEMBERS = "NestMembers";
public static final String NAME_PERMITTED_SUBCLASSES = "PermittedSubclasses";
public static final String NAME_RECORD = "Record";
public static final String NAME_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
public static final String NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
public static final String NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
public static final String NAME_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
public static final String NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
public static final String NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
public static final String NAME_SIGNATURE = "Signature";
public static final String NAME_SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
public static final String NAME_SOURCE_FILE = "SourceFile";
public static final String NAME_SOURCE_ID = "SourceID";
public static final String NAME_STACK_MAP_TABLE = "StackMapTable";
public static final String NAME_SYNTHETIC = "Synthetic";
private Attributes() {
}
/** Attribute mapper for the {@code AnnotationDefault} attribute */
public static final AttributeMapper<AnnotationDefaultAttribute>
ANNOTATION_DEFAULT = new AbstractAttributeMapper<>(NAME_ANNOTATION_DEFAULT, Classfile.JAVA_5_VERSION) {
@Override
public AnnotationDefaultAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundAnnotationDefaultAttr(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, AnnotationDefaultAttribute attr) {
attr.defaultValue().writeTo(buf);
}
};
/** Attribute mapper for the {@code BootstrapMethods} attribute */
public static final AttributeMapper<BootstrapMethodsAttribute>
BOOTSTRAP_METHODS = new AbstractAttributeMapper<>(NAME_BOOTSTRAP_METHODS, Classfile.JAVA_17_VERSION) {
@Override
public BootstrapMethodsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundBootstrapMethodsAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, BootstrapMethodsAttribute attr) {
buf.writeList(attr.bootstrapMethods());
}
};
/** Attribute mapper for the {@code CharacterRangeTable} attribute */
public static final AttributeMapper<CharacterRangeTableAttribute>
CHARACTER_RANGE_TABLE = new AbstractAttributeMapper<>(NAME_CHARACTER_RANGE_TABLE, true, Classfile.JAVA_4_VERSION) {
@Override
public CharacterRangeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundCharacterRangeTableAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, CharacterRangeTableAttribute attr) {
List<CharacterRangeInfo> ranges = attr.characterRangeTable();
buf.writeU2(ranges.size());
for (CharacterRangeInfo info : ranges) {
buf.writeU2(info.startPc());
buf.writeU2(info.endPc());
buf.writeInt(info.characterRangeStart());
buf.writeInt(info.characterRangeEnd());
buf.writeU2(info.flags());
}
}
};
/** Attribute mapper for the {@code Code} attribute */
public static final AttributeMapper<CodeAttribute>
CODE = new AbstractAttributeMapper<>(NAME_CODE) {
@Override
public CodeAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new CodeImpl(e, cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, CodeAttribute attr) {
throw new UnsupportedOperationException("Code attribute does not support direct write");
}
};
/** Attribute mapper for the {@code CompilationID} attribute */
public static final AttributeMapper<CompilationIDAttribute>
COMPILATION_ID = new AbstractAttributeMapper<>(NAME_COMPILATION_ID, true) {
@Override
public CompilationIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundCompilationIDAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, CompilationIDAttribute attr) {
buf.writeIndex(attr.compilationId());
}
};
/** Attribute mapper for the {@code ConstantValue} attribute */
public static final AttributeMapper<ConstantValueAttribute>
CONSTANT_VALUE = new AbstractAttributeMapper<>(NAME_CONSTANT_VALUE) {
@Override
public ConstantValueAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundConstantValueAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ConstantValueAttribute attr) {
buf.writeIndex(attr.constant());
}
};
/** Attribute mapper for the {@code Deprecated} attribute */
public static final AttributeMapper<DeprecatedAttribute>
DEPRECATED = new AbstractAttributeMapper<>(NAME_DEPRECATED, true) {
@Override
public DeprecatedAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundDeprecatedAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, DeprecatedAttribute attr) {
// empty
}
};
/** Attribute mapper for the {@code EnclosingMethod} attribute */
public static final AttributeMapper<EnclosingMethodAttribute>
ENCLOSING_METHOD = new AbstractAttributeMapper<>(NAME_ENCLOSING_METHOD, Classfile.JAVA_5_VERSION) {
@Override
public EnclosingMethodAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundEnclosingMethodAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, EnclosingMethodAttribute attr) {
buf.writeIndex(attr.enclosingClass());
buf.writeIndexOrZero(attr.enclosingMethod().orElse(null));
}
};
/** Attribute mapper for the {@code Exceptions} attribute */
public static final AttributeMapper<ExceptionsAttribute>
EXCEPTIONS = new AbstractAttributeMapper<>(NAME_EXCEPTIONS) {
@Override
public ExceptionsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundExceptionsAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ExceptionsAttribute attr) {
buf.writeListIndices(attr.exceptions());
}
};
/** Attribute mapper for the {@code InnerClasses} attribute */
public static final AttributeMapper<InnerClassesAttribute>
INNER_CLASSES = new AbstractAttributeMapper<>(NAME_INNER_CLASSES) {
@Override
public InnerClassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundInnerClassesAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, InnerClassesAttribute attr) {
List<InnerClassInfo> classes = attr.classes();
buf.writeU2(classes.size());
for (InnerClassInfo ic : classes) {
buf.writeIndex(ic.innerClass());
buf.writeIndexOrZero(ic.outerClass().orElse(null));
buf.writeIndexOrZero(ic.innerName().orElse(null));
buf.writeU2(ic.flagsMask());
}
}
};
/** Attribute mapper for the {@code LineNumberTable} attribute */
public static final AttributeMapper<LineNumberTableAttribute>
LINE_NUMBER_TABLE = new AbstractAttributeMapper<>(NAME_LINE_NUMBER_TABLE, true) {
@Override
public LineNumberTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundLineNumberTableAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, LineNumberTableAttribute attr) {
List<LineNumberInfo> lines = attr.lineNumbers();
buf.writeU2(lines.size());
for (LineNumberInfo line : lines) {
buf.writeU2(line.startPc());
buf.writeU2(line.lineNumber());
}
}
};
/** Attribute mapper for the {@code LocalVariableTable} attribute */
public static final AttributeMapper<LocalVariableTableAttribute>
LOCAL_VARIABLE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TABLE, true) {
@Override
public LocalVariableTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundLocalVariableTableAttribute(e, cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, LocalVariableTableAttribute attr) {
List<LocalVariableInfo> infos = attr.localVariables();
buf.writeU2(infos.size());
for (LocalVariableInfo info : infos) {
buf.writeU2(info.startPc());
buf.writeU2(info.length());
buf.writeIndex(info.name());
buf.writeIndex(info.type());
buf.writeU2(info.slot());
}
}
};
/** Attribute mapper for the {@code LocalVariableTypeTable} attribute */
public static final AttributeMapper<LocalVariableTypeTableAttribute>
LOCAL_VARIABLE_TYPE_TABLE = new AbstractAttributeMapper<>(NAME_LOCAL_VARIABLE_TYPE_TABLE, true, Classfile.JAVA_5_VERSION) {
@Override
public LocalVariableTypeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundLocalVariableTypeTableAttribute(e, cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, LocalVariableTypeTableAttribute attr) {
List<LocalVariableTypeInfo> infos = attr.localVariableTypes();
buf.writeU2(infos.size());
for (LocalVariableTypeInfo info : infos) {
buf.writeU2(info.startPc());
buf.writeU2(info.length());
buf.writeIndex(info.name());
buf.writeIndex(info.signature());
buf.writeU2(info.slot());
}
}
};
/** Attribute mapper for the {@code MethodParameters} attribute */
public static final AttributeMapper<MethodParametersAttribute>
METHOD_PARAMETERS = new AbstractAttributeMapper<>(NAME_METHOD_PARAMETERS, Classfile.JAVA_8_VERSION) {
@Override
public MethodParametersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundMethodParametersAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, MethodParametersAttribute attr) {
List<MethodParameterInfo> parameters = attr.parameters();
buf.writeU1(parameters.size());
for (MethodParameterInfo info : parameters) {
buf.writeIndexOrZero(info.name().orElse(null));
buf.writeU2(info.flagsMask());
}
}
};
/** Attribute mapper for the {@code Module} attribute */
public static final AttributeMapper<ModuleAttribute>
MODULE = new AbstractAttributeMapper<>(NAME_MODULE, Classfile.JAVA_9_VERSION) {
@Override
public ModuleAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModuleAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModuleAttribute attr) {
buf.writeIndex(attr.moduleName());
buf.writeU2(attr.moduleFlagsMask());
buf.writeIndexOrZero(attr.moduleVersion().orElse(null));
buf.writeU2(attr.requires().size());
for (ModuleRequireInfo require : attr.requires()) {
buf.writeIndex(require.requires());
buf.writeU2(require.requiresFlagsMask());
buf.writeIndexOrZero(require.requiresVersion().orElse(null));
}
buf.writeU2(attr.exports().size());
for (ModuleExportInfo export : attr.exports()) {
buf.writeIndex(export.exportedPackage());
buf.writeU2(export.exportsFlagsMask());
buf.writeListIndices(export.exportsTo());
}
buf.writeU2(attr.opens().size());
for (ModuleOpenInfo open : attr.opens()) {
buf.writeIndex(open.openedPackage());
buf.writeU2(open.opensFlagsMask());
buf.writeListIndices(open.opensTo());
}
buf.writeListIndices(attr.uses());
buf.writeU2(attr.provides().size());
for (ModuleProvideInfo provide : attr.provides()) {
buf.writeIndex(provide.provides());
buf.writeListIndices(provide.providesWith());
}
}
};
/** Attribute mapper for the {@code ModuleHashes} attribute */
public static final AttributeMapper<ModuleHashesAttribute>
MODULE_HASHES = new AbstractAttributeMapper<>(NAME_MODULE_HASHES, Classfile.JAVA_9_VERSION) {
@Override
public ModuleHashesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModuleHashesAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModuleHashesAttribute attr) {
buf.writeIndex(attr.algorithm());
List<ModuleHashInfo> hashes = attr.hashes();
buf.writeU2(hashes.size());
for (ModuleHashInfo hash : hashes) {
buf.writeIndex(hash.moduleName());
buf.writeU2(hash.hash().length);
buf.writeBytes(hash.hash());
}
}
};
/** Attribute mapper for the {@code ModuleMainClass} attribute */
public static final AttributeMapper<ModuleMainClassAttribute>
MODULE_MAIN_CLASS = new AbstractAttributeMapper<>(NAME_MODULE_MAIN_CLASS, Classfile.JAVA_9_VERSION) {
@Override
public ModuleMainClassAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModuleMainClassAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModuleMainClassAttribute attr) {
buf.writeIndex(attr.mainClass());
}
};
/** Attribute mapper for the {@code ModulePackages} attribute */
public static final AttributeMapper<ModulePackagesAttribute>
MODULE_PACKAGES = new AbstractAttributeMapper<>(NAME_MODULE_PACKAGES, Classfile.JAVA_9_VERSION) {
@Override
public ModulePackagesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModulePackagesAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) {
buf.writeListIndices(attr.packages());
}
};
/** Attribute mapper for the {@code ModuleResolution} attribute */
public static final AttributeMapper<ModuleResolutionAttribute>
MODULE_RESOLUTION = new AbstractAttributeMapper<>(NAME_MODULE_RESOLUTION, true, Classfile.JAVA_9_VERSION) {
@Override
public ModuleResolutionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModuleResolutionAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModuleResolutionAttribute attr) {
buf.writeU2(attr.resolutionFlags());
}
};
/** Attribute mapper for the {@code ModuleTarget} attribute */
public static final AttributeMapper<ModuleTargetAttribute>
MODULE_TARGET = new AbstractAttributeMapper<>(NAME_MODULE_TARGET, true, Classfile.JAVA_9_VERSION) {
@Override
public ModuleTargetAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundModuleTargetAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, ModuleTargetAttribute attr) {
buf.writeIndex(attr.targetPlatform());
}
};
/** Attribute mapper for the {@code NestHost} attribute */
public static final AttributeMapper<NestHostAttribute>
NEST_HOST = new AbstractAttributeMapper<>(NAME_NEST_HOST, Classfile.JAVA_11_VERSION) {
@Override
public NestHostAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundNestHostAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, NestHostAttribute attr) {
buf.writeIndex(attr.nestHost());
}
};
/** Attribute mapper for the {@code NestMembers} attribute */
public static final AttributeMapper<NestMembersAttribute>
NEST_MEMBERS = new AbstractAttributeMapper<>(NAME_NEST_MEMBERS, Classfile.JAVA_11_VERSION) {
@Override
public NestMembersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundNestMembersAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, NestMembersAttribute attr) {
buf.writeListIndices(attr.nestMembers());
}
};
/** Attribute mapper for the {@code PermittedSubclasses} attribute */
public static final AttributeMapper<PermittedSubclassesAttribute>
PERMITTED_SUBCLASSES = new AbstractAttributeMapper<>(NAME_PERMITTED_SUBCLASSES, Classfile.JAVA_15_VERSION) {
@Override
public PermittedSubclassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundPermittedSubclassesAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) {
buf.writeListIndices(attr.permittedSubclasses());
}
};
/** Attribute mapper for the {@code Record} attribute */
public static final AttributeMapper<RecordAttribute>
RECORD = new AbstractAttributeMapper<>(NAME_RECORD, Classfile.JAVA_16_VERSION) {
@Override
public RecordAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundRecordAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, RecordAttribute attr) {
List<RecordComponentInfo> components = attr.components();
buf.writeU2(components.size());
for (RecordComponentInfo info : components) {
buf.writeIndex(info.name());
buf.writeIndex(info.descriptor());
buf.writeList(info.attributes());
}
}
};
/** Attribute mapper for the {@code RuntimeInvisibleAnnotations} attribute */
public static final AttributeMapper<RuntimeInvisibleAnnotationsAttribute>
RUNTIME_INVISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_ANNOTATIONS, Classfile.JAVA_5_VERSION) {
@Override
public RuntimeInvisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
return new BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute(cf, pos);
}
@Override
protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) {
buf.writeList(attr.annotations());
}
};
/** Attribute mapper for the {@code RuntimeInvisibleParameterAnnotations} attribute */
public static final AttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute>
RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, Classfile.JAVA_5_VERSION) {
@Override
public RuntimeInvisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, RuntimeInvisibleParameterAnnotationsAttribute attr) {
List<List<Annotation>> lists = attr.parameterAnnotations();
buf.writeU1(lists.size());
for (List<Annotation> list : lists)
buf.writeList(list);
}
};
/** Attribute mapper for the {@code RuntimeInvisibleTypeAnnotations} attribute */
public static final AttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute>
RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, Classfile.JAVA_8_VERSION) {
@Override
public RuntimeInvisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute(e, cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) {
buf.writeList(attr.annotations());
}
};
/** Attribute mapper for the {@code RuntimeVisibleAnnotations} attribute */
public static final AttributeMapper<RuntimeVisibleAnnotationsAttribute>
RUNTIME_VISIBLE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_ANNOTATIONS, Classfile.JAVA_5_VERSION) {
@Override
public RuntimeVisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
return new BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute(cf, pos);
}
@Override
protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) {
buf.writeList(attr.annotations());
}
};
/** Attribute mapper for the {@code RuntimeVisibleParameterAnnotations} attribute */
public static final AttributeMapper<RuntimeVisibleParameterAnnotationsAttribute>
RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, Classfile.JAVA_5_VERSION) {
@Override
public RuntimeVisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, RuntimeVisibleParameterAnnotationsAttribute attr) {
List<List<Annotation>> lists = attr.parameterAnnotations();
buf.writeU1(lists.size());
for (List<Annotation> list : lists)
buf.writeList(list);
}
};
/** Attribute mapper for the {@code RuntimeVisibleTypeAnnotations} attribute */
public static final AttributeMapper<RuntimeVisibleTypeAnnotationsAttribute>
RUNTIME_VISIBLE_TYPE_ANNOTATIONS = new AbstractAttributeMapper<>(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, Classfile.JAVA_8_VERSION) {
@Override
public RuntimeVisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute(e, cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
buf.writeList(attr.annotations());
}
};
/** Attribute mapper for the {@code Signature} attribute */
public static final AttributeMapper<SignatureAttribute>
SIGNATURE = new AbstractAttributeMapper<>(NAME_SIGNATURE, Classfile.JAVA_5_VERSION) {
@Override
public SignatureAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSignatureAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, SignatureAttribute attr) {
buf.writeIndex(attr.signature());
}
};
/** Attribute mapper for the {@code SourceDebug} attribute */
public static final AttributeMapper<SourceDebugExtensionAttribute>
SOURCE_DEBUG_EXTENSION = new AbstractAttributeMapper<>(NAME_SOURCE_DEBUG_EXTENSION, Classfile.JAVA_5_VERSION) {
@Override
public SourceDebugExtensionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSourceDebugExtensionAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, SourceDebugExtensionAttribute attr) {
buf.writeBytes(attr.contents());
}
};
/** Attribute mapper for the {@code SourceFile} attribute */
public static final AttributeMapper<SourceFileAttribute>
SOURCE_FILE = new AbstractAttributeMapper<>(NAME_SOURCE_FILE) {
@Override
public SourceFileAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSourceFileAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, SourceFileAttribute attr) {
buf.writeIndex(attr.sourceFile());
}
};
/** Attribute mapper for the {@code SourceID} attribute */
public static final AttributeMapper<SourceIDAttribute>
SOURCE_ID = new AbstractAttributeMapper<>(NAME_SOURCE_ID) {
@Override
public SourceIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSourceIDAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, SourceIDAttribute attr) {
buf.writeIndex(attr.sourceId());
}
};
/** Attribute mapper for the {@code StackMapTable} attribute */
public static final AttributeMapper<StackMapTableAttribute>
STACK_MAP_TABLE = new AbstractAttributeMapper<>(NAME_STACK_MAP_TABLE, Classfile.JAVA_6_VERSION) {
@Override
public StackMapTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundStackMapTableAttribute((CodeImpl)e, cf, this, p);
}
@Override
protected void writeBody(BufWriter b, StackMapTableAttribute attr) {
StackMapDecoder.writeFrames(b, attr.entries());
}
};
/** Attribute mapper for the {@code Synthetic} attribute */
public static final AttributeMapper<SyntheticAttribute>
SYNTHETIC = new AbstractAttributeMapper<>(NAME_SYNTHETIC) {
@Override
public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
return new BoundAttribute.BoundSyntheticAttribute(cf, this, p);
}
@Override
protected void writeBody(BufWriter buf, SyntheticAttribute attr) {
// empty
}
};
/**
* {@return the attribute mapper for a standard attribute}
*
* @param name the name of the attribute to find
*/
public static AttributeMapper<?> standardAttribute(Utf8Entry name) {
return _ATTR_MAP.get(name);
}
/**
* All standard attribute mappers.
*/
public static final Set<AttributeMapper<?>> PREDEFINED_ATTRIBUTES = Set.of(
ANNOTATION_DEFAULT,
BOOTSTRAP_METHODS,
CHARACTER_RANGE_TABLE,
CODE,
COMPILATION_ID,
CONSTANT_VALUE,
DEPRECATED,
ENCLOSING_METHOD,
EXCEPTIONS,
INNER_CLASSES,
LINE_NUMBER_TABLE,
LOCAL_VARIABLE_TABLE,
LOCAL_VARIABLE_TYPE_TABLE,
METHOD_PARAMETERS,
MODULE,
MODULE_HASHES,
MODULE_MAIN_CLASS,
MODULE_PACKAGES,
MODULE_RESOLUTION,
MODULE_TARGET,
NEST_HOST,
NEST_MEMBERS,
PERMITTED_SUBCLASSES,
RECORD,
RUNTIME_INVISIBLE_ANNOTATIONS,
RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
RUNTIME_INVISIBLE_TYPE_ANNOTATIONS,
RUNTIME_VISIBLE_ANNOTATIONS,
RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
RUNTIME_VISIBLE_TYPE_ANNOTATIONS,
SIGNATURE,
SOURCE_DEBUG_EXTENSION,
SOURCE_FILE,
SOURCE_ID,
STACK_MAP_TABLE,
SYNTHETIC);
private static final Map<Utf8Entry, AttributeMapper<?>> _ATTR_MAP;
//no lambdas here as this is on critical JDK boostrap path
static {
var map = new HashMap<Utf8Entry, AttributeMapper<?>>(64);
for (var am : PREDEFINED_ATTRIBUTES) {
map.put(AbstractPoolEntry.rawUtf8EntryFromStandardAttributeName(am.name()), am);
}
_ATTR_MAP = Collections.unmodifiableMap(map);
}
}

View File

@ -0,0 +1,64 @@
/*
* 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 jdk.internal.classfile;
import java.util.List;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.constantpool.LoadableConstantEntry;
import jdk.internal.classfile.constantpool.MethodHandleEntry;
import jdk.internal.classfile.impl.BootstrapMethodEntryImpl;
/**
* Models an entry in the bootstrap method table. The bootstrap method table
* is stored in the {@code BootstrapMethods} attribute, but is modeled by
* the {@link ConstantPool}, since the bootstrap method table is logically
* part of the constant pool.
*/
public sealed interface BootstrapMethodEntry
extends WritableElement<BootstrapMethodEntry>
permits BootstrapMethodEntryImpl {
/**
* {@return the constant pool associated with this entry}
*/
ConstantPool constantPool();
/**
* {@return the index into the bootstrap method table corresponding to this entry}
*/
int bsmIndex();
/**
* {@return the bootstrap method}
*/
MethodHandleEntry bootstrapMethod();
/**
* {@return the bootstrap arguments}
*/
List<LoadableConstantEntry> arguments();
}

View File

@ -0,0 +1,200 @@
/*
* 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 jdk.internal.classfile;
import java.nio.ByteBuffer;
import java.util.List;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.constantpool.ConstantPoolBuilder;
import jdk.internal.classfile.constantpool.PoolEntry;
import jdk.internal.classfile.impl.BufWriterImpl;
/**
* Supports writing portions of a classfile to a growable buffer. Method
* are provided to write various standard entities (e.g., {@code u2}, {@code u4})
* to the end of the buffer, as well as to create constant pool entries.
*/
public sealed interface BufWriter
permits BufWriterImpl {
/** {@return the constant pool builder associated with this buffer} */
ConstantPoolBuilder constantPool();
/**
* {@return whether the provided constant pool is index-compatible with this
* one} This may be because they are the same constant pool, or because this
* constant pool was copied from the other.
*
* @param other the other constant pool
*/
boolean canWriteDirect(ConstantPool other);
/**
* Ensure that the buffer has at least {@code freeBytes} bytes of unused space
* @param freeBytes the number of bytes to reserve
*/
void reserveSpace(int freeBytes);
/**
* Write an unsigned byte to the buffer
*
* @param x the byte value
*/
void writeU1(int x);
/**
* Write an unsigned short to the buffer
*
* @param x the short value
*/
void writeU2(int x);
/**
* Write a signed int to the buffer
*
* @param x the int value
*/
void writeInt(int x);
/**
* Write a float value to the buffer
*
* @param x the float value
*/
void writeFloat(float x);
/**
* Write a long value to the buffer
*
* @param x the long value
*/
void writeLong(long x);
/**
* Write a double value to the buffer
*
* @param x the int value
*/
void writeDouble(double x);
/**
* Write the contents of a byte array to the buffer
*
* @param arr the byte array
*/
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
*
* @param arr the byte array
* @param start the offset within the byte array of the range
* @param length the length of the range
*/
void writeBytes(byte[] arr, int start, int length);
/**
* Patch a previously written integer value. Depending on the specified
* size, the entire value, or the low 1 or 2 bytes, may be written.
*
* @param offset the offset at which to patch
* @param size the size of the integer value being written, in bytes
* @param value the integer value
*/
void patchInt(int offset, int size, int value);
/**
* Write a 1, 2, 4, or 8 byte integer value to the buffer. Depending on
* the specified size, the entire value, or the low 1, 2, or 4 bytes, may
* be written.
*
* @param intSize the size of the integer value being written, in bytes
* @param intValue the integer value
*/
void writeIntBytes(int intSize, long intValue);
/**
* Write the index of the specified constant pool entry, as a {@code u2},
* to the buffer
*
* @param entry the constant pool entry
* @throws NullPointerException if the entry is null
*/
void writeIndex(PoolEntry entry);
/**
* Write the index of the specified constant pool entry, as a {@code u2},
* to the buffer, or zero if the entry is null
*
* @param entry the constant pool entry
*/
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
*/
void writeListIndices(List<? extends PoolEntry> list);
/**
* {@return the number of bytes that have been written to the buffer}
*/
int size();
/**
* {@return a {@link java.nio.ByteBuffer ByteBuffer} view of the bytes in the buffer}
*/
ByteBuffer asByteBuffer();
/**
* 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
*/
void copyTo(byte[] array, int bufferOffset);
}

View File

@ -0,0 +1,299 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.ChainedClassBuilder;
import jdk.internal.classfile.impl.DirectClassBuilder;
import jdk.internal.classfile.impl.Util;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.attribute.CodeAttribute;
/**
* A builder for classfiles. Builders are not created directly; they are passed
* to handlers by methods such as {@link Classfile#build(ClassDesc, Consumer)}
* or to class transforms. The elements of a classfile can be specified
* abstractly (by passing a {@link ClassElement} to {@link #with(ClassfileElement)})
* or concretely by calling the various {@code withXxx} methods.
*
* @see ClassTransform
*/
public sealed interface ClassBuilder
extends ClassfileBuilder<ClassElement, ClassBuilder>
permits ChainedClassBuilder, DirectClassBuilder {
/**
* {@return the {@link ClassModel} representing the class being transformed,
* if this class builder represents the transformation of some {@link ClassModel}}
*/
Optional<ClassModel> original();
/**
* Sets the classfile version.
* @param major the major version number
* @param minor the minor version number
* @return this builder
*/
default ClassBuilder withVersion(int major, int minor) {
return with(ClassfileVersion.of(major, minor));
}
/**
* Sets the classfile access flags.
* @param flags the access flags, as a bit mask
* @return this builder
*/
default ClassBuilder withFlags(int flags) {
return with(AccessFlags.ofClass(flags));
}
/**
* Sets the classfile access flags.
* @param flags the access flags
* @return this builder
*/
default ClassBuilder withFlags(AccessFlag... flags) {
return with(AccessFlags.ofClass(flags));
}
/**
* Sets the superclass of this class.
* @param superclassEntry the superclass
* @return this builder
*/
default ClassBuilder withSuperclass(ClassEntry superclassEntry) {
return with(Superclass.of(superclassEntry));
}
/**
* Sets the superclass of this class.
* @param desc the superclass
* @return this builder
*/
default ClassBuilder withSuperclass(ClassDesc desc) {
return withSuperclass(constantPool().classEntry(desc));
}
/**
* Sets the interfaces of this class.
* @param interfaces the interfaces
* @return this builder
*/
default ClassBuilder withInterfaces(List<ClassEntry> interfaces) {
return with(Interfaces.of(interfaces));
}
/**
* Sets the interfaces of this class.
* @param interfaces the interfaces
* @return this builder
*/
default ClassBuilder withInterfaces(ClassEntry... interfaces) {
return withInterfaces(List.of(interfaces));
}
/**
* Sets the interfaces of this class.
* @param interfaces the interfaces
* @return this builder
*/
default ClassBuilder withInterfaceSymbols(List<ClassDesc> interfaces) {
return withInterfaces(Util.entryList(interfaces));
}
/**
* Sets the interfaces of this class.
* @param interfaces the interfaces
* @return this builder
*/
default ClassBuilder withInterfaceSymbols(ClassDesc... interfaces) {
// List view, since ref to interfaces is temporary
return withInterfaceSymbols(Arrays.asList(interfaces));
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
* @return this builder
*/
ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
Consumer<? super FieldBuilder> handler);
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* @return this builder
*/
default ClassBuilder withField(Utf8Entry name,
Utf8Entry descriptor,
int flags) {
return withField(name, descriptor, fb -> fb.withFlags(flags));
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param handler handler which receives a {@link FieldBuilder} which can
* further define the contents of the field
* @return this builder
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
Consumer<? super FieldBuilder> handler) {
return withField(constantPool().utf8Entry(name),
constantPool().utf8Entry(descriptor),
handler);
}
/**
* Adds a field.
* @param name the name of the field
* @param descriptor the field descriptor
* @param flags the access flags for this field
* @return this builder
*/
default ClassBuilder withField(String name,
ClassDesc descriptor,
int flags) {
return withField(name, descriptor, fb -> fb.withFlags(flags));
}
/**
* Adds a field by transforming a field from another class.
*
* @implNote
* <p>This method behaves as if:
* {@snippet lang=java :
* withField(field.fieldName(), field.fieldType(),
* b -> b.transformField(field, transform));
* }
*
* @param field the field to be transformed
* @param transform the transform to apply to the field
* @return this builder
*/
ClassBuilder transformField(FieldModel field, FieldTransform transform);
/**
* Adds a method.
* @param name the name of the method
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @return this builder
*/
ClassBuilder withMethod(Utf8Entry name,
Utf8Entry descriptor,
int methodFlags,
Consumer<? super MethodBuilder> handler);
/**
* Adds a method, with only a {@code Code} attribute.
*
* @param name the name of the method
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @return this builder
*/
default ClassBuilder withMethodBody(Utf8Entry name,
Utf8Entry descriptor,
int methodFlags,
Consumer<? super CodeBuilder> handler) {
return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler));
}
/**
* Adds a method.
* @param name the name of the method
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link MethodBuilder} which can
* further define the contents of the method
* @return this builder
*/
default ClassBuilder withMethod(String name,
MethodTypeDesc descriptor,
int methodFlags,
Consumer<? super MethodBuilder> handler) {
return withMethod(constantPool().utf8Entry(name),
constantPool().utf8Entry(descriptor),
methodFlags,
handler);
}
/**
* Adds a method, with only a {@link CodeAttribute}.
* @param name the name of the method
* @param descriptor the method descriptor
* @param methodFlags the access flags
* @param handler handler which receives a {@link CodeBuilder} which can
* define the contents of the method body
* @return this builder
*/
default ClassBuilder withMethodBody(String name,
MethodTypeDesc descriptor,
int methodFlags,
Consumer<? super CodeBuilder> handler) {
return withMethodBody(constantPool().utf8Entry(name),
constantPool().utf8Entry(descriptor),
methodFlags,
handler);
}
/**
* Adds a method by transforming a method from another class.
*
* @implNote
* <p>This method behaves as if:
* {@snippet lang=java :
* withMethod(method.methodName(), method.methodType(),
* b -> b.transformMethod(method, transform));
* }
* @param method the method to be transformed
* @param transform the transform to apply to the method
* @return this builder
*/
ClassBuilder transformMethod(MethodModel method, MethodTransform transform);
}

View File

@ -0,0 +1,69 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.CompilationIDAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.EnclosingMethodAttribute;
import jdk.internal.classfile.attribute.InnerClassesAttribute;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.ModuleHashesAttribute;
import jdk.internal.classfile.attribute.ModuleMainClassAttribute;
import jdk.internal.classfile.attribute.ModulePackagesAttribute;
import jdk.internal.classfile.attribute.ModuleResolutionAttribute;
import jdk.internal.classfile.attribute.ModuleTargetAttribute;
import jdk.internal.classfile.attribute.NestHostAttribute;
import jdk.internal.classfile.attribute.NestMembersAttribute;
import jdk.internal.classfile.attribute.PermittedSubclassesAttribute;
import jdk.internal.classfile.attribute.RecordAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.SignatureAttribute;
import jdk.internal.classfile.attribute.SourceDebugExtensionAttribute;
import jdk.internal.classfile.attribute.SourceFileAttribute;
import jdk.internal.classfile.attribute.SourceIDAttribute;
import jdk.internal.classfile.attribute.SyntheticAttribute;
import jdk.internal.classfile.attribute.UnknownAttribute;
/**
* A {@link ClassfileElement} that can appear when traversing the elements
* of a {@link ClassModel} or be presented to a {@link ClassBuilder}.
*/
public sealed interface ClassElement extends ClassfileElement
permits AccessFlags, Superclass, Interfaces, ClassfileVersion,
FieldModel, MethodModel,
CustomAttribute, CompilationIDAttribute, DeprecatedAttribute,
EnclosingMethodAttribute, InnerClassesAttribute,
ModuleAttribute, ModuleHashesAttribute, ModuleMainClassAttribute,
ModulePackagesAttribute, ModuleResolutionAttribute, ModuleTargetAttribute,
NestHostAttribute, NestMembersAttribute, PermittedSubclassesAttribute,
RecordAttribute,
RuntimeInvisibleAnnotationsAttribute, RuntimeInvisibleTypeAnnotationsAttribute,
RuntimeVisibleAnnotationsAttribute, RuntimeVisibleTypeAnnotationsAttribute,
SignatureAttribute, SourceDebugExtensionAttribute,
SourceFileAttribute, SourceIDAttribute, SyntheticAttribute, UnknownAttribute {
}

View File

@ -0,0 +1,115 @@
/*
* 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 jdk.internal.classfile;
import java.io.InputStream;
import java.lang.constant.ClassDesc;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import jdk.internal.classfile.impl.Util;
import jdk.internal.classfile.impl.ClassHierarchyImpl;
/**
* Provides class hierarchy information for generating correct stack maps
* during code building.
*/
@FunctionalInterface
public interface ClassHierarchyResolver {
/**
* Default singleton instance of {@linkplain ClassHierarchyResolver}
* using {@link ClassLoader#getSystemResourceAsStream(String)}
* as the {@code ClassStreamResolver}
*/
ClassHierarchyResolver DEFAULT_CLASS_HIERARCHY_RESOLVER
= new ClassHierarchyImpl.CachedClassHierarchyResolver(
new Function<ClassDesc, InputStream>() {
@Override
public InputStream apply(ClassDesc classDesc) {
return ClassLoader.getSystemResourceAsStream(Util.toInternalName(classDesc) + ".class");
}
});
/**
* {@return the {@link ClassHierarchyInfo} for a given class name, or null
* if the name is unknown to the resolver}
* @param classDesc descriptor of the class
*/
ClassHierarchyInfo getClassInfo(ClassDesc classDesc);
/**
* Chains this {@linkplain ClassHierarchyResolver} with another to be
* consulted if this resolver does not know about the specified class.
*
* @param other the other resolver
* @return the chained resolver
*/
default ClassHierarchyResolver orElse(ClassHierarchyResolver other) {
return new ClassHierarchyResolver() {
@Override
public ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
var chi = ClassHierarchyResolver.this.getClassInfo(classDesc);
if (chi == null)
chi = other.getClassInfo(classDesc);
return chi;
}
};
}
/**
* Information about a resolved class.
* @param thisClass descriptor of this class
* @param isInterface whether this class is an interface
* @param superClass descriptor of the superclass (not relevant for interfaces)
*/
public record ClassHierarchyInfo(ClassDesc thisClass, boolean isInterface, ClassDesc superClass) {
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from classfiles located by a mapping function
*
* @param classStreamResolver maps class descriptors to classfile input streams
* @return the {@linkplain ClassHierarchyResolver}
*/
public static ClassHierarchyResolver ofCached(Function<ClassDesc, InputStream> classStreamResolver) {
return new ClassHierarchyImpl.CachedClassHierarchyResolver(classStreamResolver);
}
/**
* Returns a {@linkplain ClassHierarchyResolver} that extracts class hierarchy
* information from collections of class hierarchy metadata
*
* @param interfaces a collection of classes known to be interfaces
* @param classToSuperClass a map from classes to their super classes
* @return the {@linkplain ClassHierarchyResolver}
*/
public static ClassHierarchyResolver of(Collection<ClassDesc> interfaces,
Map<ClassDesc, ClassDesc> classToSuperClass) {
return new ClassHierarchyImpl.StaticClassHierarchyResolver(interfaces, classToSuperClass);
}
}

View File

@ -0,0 +1,121 @@
/*
* 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 jdk.internal.classfile;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.impl.ClassImpl;
import jdk.internal.classfile.impl.verifier.VerifierImpl;
/**
* Models a classfile. The contents of the classfile can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*/
public sealed interface ClassModel
extends CompoundElement<ClassElement>, AttributedElement
permits ClassImpl {
/**
* {@return the constant pool for this class}
*/
ConstantPool constantPool();
/** {@return the access flags} */
AccessFlags flags();
/** {@return the constant pool entry describing the name of this class} */
ClassEntry thisClass();
/** {@return the major classfile version} */
int majorVersion();
/** {@return the minor classfile version} */
int minorVersion();
/** {@return the fields of this class} */
List<FieldModel> fields();
/** {@return the methods of this class} */
List<MethodModel> methods();
/** {@return the superclass of this class, if there is one} */
Optional<ClassEntry> superclass();
/** {@return the interfaces implemented by this class} */
List<ClassEntry> interfaces();
/**
* Transform this classfile into a new classfile with the aid of a
* {@link ClassTransform}. The transform will receive each element of
* this class, as well as a {@link ClassBuilder} for building the new class.
* The transform is free to preserve, remove, or replace elements as it
* sees fit.
*
* @implNote
* <p>This method behaves as if:
* {@snippet lang=java :
* Classfile.build(thisClass(), ConstantPoolBuilder.of(this),
* b -> b.transform(this, transform));
* }
*
* @param transform the transform
* @return the bytes of the new class
*/
byte[] transform(ClassTransform transform);
/** {@return whether this class is a module descriptor} */
boolean isModuleInfo();
/**
* Verify this classfile. Any verification errors found will be returned.
*
* @param debugOutput handler to receive debug information
* @return a list of verification errors, or an empty list if no errors are
* found
*/
default List<VerifyError> verify(Consumer<String> debugOutput) {
return VerifierImpl.verify(this, debugOutput);
}
/**
* Verify this classfile. Any verification errors found will be returned.
*
* @param debugOutput handler to receive debug information
* @param classHierarchyResolver class hierarchy resolver to provide
* additional information about the class hiearchy
* @return a list of verification errors, or an empty list if no errors are
* found
*/
default List<VerifyError> verify(ClassHierarchyResolver classHierarchyResolver,
Consumer<String> debugOutput) {
return VerifierImpl.verify(this, classHierarchyResolver, debugOutput);
}
}

View File

@ -0,0 +1,270 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.constantpool.MethodHandleEntry;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.NameAndTypeEntry;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.constantpool.PoolEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.ClassReaderImpl;
import java.util.Optional;
import java.util.function.Function;
/**
* Supports reading from a classfile. Methods are provided to read data of
* various numeric types (e.g., {@code u2}, {@code u4}) at a given offset within
* the classfile, copying raw bytes, and reading constant pool entries.
* Encapsulates additional reading context such as mappers for custom attributes
* and processing options.
*/
public sealed interface ClassReader extends ConstantPool
permits ClassReaderImpl {
// Processing context
/**
* {@return the table of custom attribute mappers} This is derived from
* the processing option {@link Classfile.Option#attributeMapper(Function)}.
*/
Function<Utf8Entry, AttributeMapper<?>> customAttributes();
// Class context
/** {@return the access flags for the class, as a bit mask } */
int flags();
/** {@return the constant pool entry describing the name of class} */
ClassEntry thisClassEntry();
/** {@return the constant pool entry describing the name of the superclass, if any} */
Optional<ClassEntry> superclassEntry();
/** {@return the offset into the classfile of the {@code this_class} field} */
int thisClassPos();
/** {@return the length of the classfile, in bytes} */
int classfileLength();
// Buffer related
/**
* {@return the offset following the block of attributes starting at the
* specified position}
* @param offset the offset into the classfile at which the attribute block
* starts
*/
int skipAttributeHolder(int offset);
// Constant pool
/**
* {@return the UTF8 constant pool entry at the given index of the constant
* pool} The given index must correspond to a valid constant pool index
* whose slot holds a UTF8 constant.
* @param index the index into the constant pool
*/
Utf8Entry utf8EntryByIndex(int index);
/**
* {@return the constant pool entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
*/
PoolEntry readEntry(int offset);
/**
* {@return the constant pool entry whose index is given at the specified
* offset within the classfile, or null if the index at the specified
* offset is zero}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size
*/
PoolEntry readEntryOrNull(int offset);
/**
* {@return the UTF8 entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a UTF8 entry
*/
Utf8Entry readUtf8Entry(int offset);
/**
* {@return the UTF8 entry whose index is given at the specified
* offset within the classfile, or null if the index at the specified
* offset is zero}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size
* @throws IllegalArgumentException if the index does not correspond to
* a UTF8 entry
*/
Utf8Entry readUtf8EntryOrNull(int offset);
/**
* {@return the module entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a module entry
*/
ModuleEntry readModuleEntry(int offset);
/**
* {@return the package entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a package entry
*/
PackageEntry readPackageEntry(int offset);
/**
* {@return the class entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a class entry
*/
ClassEntry readClassEntry(int offset);
/**
* {@return the name-and-type entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a name-and-type entry
*/
NameAndTypeEntry readNameAndTypeEntry(int offset);
/**
* {@return the method handle entry whose index is given at the specified
* offset within the classfile}
* @param offset the offset of the index within the classfile
* @throws IndexOutOfBoundsException if the index is out of range of the
* constant pool size, or zero
* @throws IllegalArgumentException if the index does not correspond to
* a method handle entry
*/
MethodHandleEntry readMethodHandleEntry(int offset);
/**
* {@return the unsigned byte at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
int readU1(int offset);
/**
* {@return the unsigned short at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
int readU2(int offset);
/**
* {@return the signed byte at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
int readS1(int offset);
/**
* {@return the signed byte at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
int readS2(int offset);
/**
* {@return the signed int at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
int readInt(int offset);
/**
* {@return the signed long at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
long readLong(int offset);
/**
* {@return the float value at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
float readFloat(int offset);
/**
* {@return the double value at the specified offset within the classfile}
* @param offset the offset within the classfile
*/
double readDouble(int offset);
/**
* {@return a copy of the bytes at the specified range in the classfile}
* @param offset the offset within the classfile
* @param len the length of the range
*/
byte[] readBytes(int offset, int len);
/**
* Copy a range of bytes from the classfile to a {@link BufWriter}
*
* @param buf the {@linkplain BufWriter}
* @param offset the offset within the classfile
* @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

@ -0,0 +1,82 @@
/*
* 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 jdk.internal.classfile;
import java.util.List;
import jdk.internal.classfile.impl.SignaturesImpl;
import static java.util.Objects.requireNonNull;
/**
* Models the generic signature of a class file, as defined by {@jvms 4.7.9}.
*/
public sealed interface ClassSignature
permits SignaturesImpl.ClassSignatureImpl {
/** {@return the type parameters of this class} */
List<Signature.TypeParam> typeParameters();
/** {@return the instantiation of the superclass in this signature} */
Signature.RefTypeSig superclassSignature();
/** {@return the instantiation of the interfaces in this signature} */
List<Signature.RefTypeSig> superinterfaceSignatures();
/** {@return the raw signature string} */
String signatureString();
/**
* @return class signature
* @param superclassSignature the superclass
* @param superinterfaceSignatures the interfaces
*/
public static ClassSignature of(Signature.RefTypeSig superclassSignature,
Signature.RefTypeSig... superinterfaceSignatures) {
return of(List.of(), superclassSignature, superinterfaceSignatures);
}
/**
* @return class signature
* @param typeParameters the type parameters
* @param superclassSignature the superclass
* @param superinterfaceSignatures the interfaces
*/
public static ClassSignature of(List<Signature.TypeParam> typeParameters,
Signature.RefTypeSig superclassSignature,
Signature.RefTypeSig... superinterfaceSignatures) {
return new SignaturesImpl.ClassSignatureImpl(
requireNonNull(typeParameters),
requireNonNull(superclassSignature),
List.of(superinterfaceSignatures));
}
/**
* Parses a raw class signature string into a {@linkplain Signature}
* @param classSignature the raw class signature string
* @return class signature
*/
public static ClassSignature parseFrom(String classSignature) {
return new SignaturesImpl().parseClassSignature(requireNonNull(classSignature));
}
}

View File

@ -0,0 +1,170 @@
/*
* 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 jdk.internal.classfile;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import jdk.internal.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A transformation on streams of {@link ClassElement}.
*
* @see ClassfileTransform
*/
@FunctionalInterface
public non-sealed interface ClassTransform
extends ClassfileTransform<ClassTransform, ClassElement, ClassBuilder> {
/**
* A class transform that sends all elements to the builder.
*/
static final ClassTransform ACCEPT_ALL = new ClassTransform() {
@Override
public void accept(ClassBuilder builder, ClassElement element) {
builder.with(element);
}
};
/**
* Create a stateful class transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
* for each traversal
* @return the stateful class transform
*/
static ClassTransform ofStateful(Supplier<ClassTransform> supplier) {
return new TransformImpl.SupplierClassTransform(supplier);
}
/**
* Create a class transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
* @return the class transform
*/
static ClassTransform endHandler(Consumer<ClassBuilder> finisher) {
return new ClassTransform() {
@Override
public void accept(ClassBuilder builder, ClassElement element) {
builder.with(element);
}
@Override
public void atEnd(ClassBuilder builder) {
finisher.accept(builder);
}
};
}
/**
* Create a class transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop
* @return the class transform
*/
static ClassTransform dropping(Predicate<ClassElement> filter) {
return (b, e) -> {
if (!filter.test(e))
b.with(e);
};
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
*
* @param filter a predicate that determines which methods to transform
* @param xform the method transform
* @return the class transform
*/
static ClassTransform transformingMethods(Predicate<MethodModel> filter,
MethodTransform xform) {
return new TransformImpl.ClassMethodTransform(xform, filter);
}
/**
* Create a class transform that transforms {@link MethodModel} elements
* with the supplied method transform.
*
* @param xform the method transform
* @return the class transform
*/
static ClassTransform transformingMethods(MethodTransform xform) {
return transformingMethods(mm -> true, xform);
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
*
* @param filter a predicate that determines which methods to transform
* @param xform the code transform
* @return the class transform
*/
static ClassTransform transformingMethodBodies(Predicate<MethodModel> filter,
CodeTransform xform) {
return transformingMethods(filter, MethodTransform.transformingCode(xform));
}
/**
* Create a class transform that transforms the {@link CodeAttribute} (method body)
* of {@link MethodModel} elements with the supplied code transform.
*
* @param xform the code transform
* @return the class transform
*/
static ClassTransform transformingMethodBodies(CodeTransform xform) {
return transformingMethods(MethodTransform.transformingCode(xform));
}
/**
* Create a class transform that transforms {@link FieldModel} elements
* with the supplied field transform.
*
* @param xform the field transform
* @return the class transform
*/
static ClassTransform transformingFields(FieldTransform xform) {
return new TransformImpl.ClassFieldTransform(xform, f -> true);
}
@Override
default ClassTransform andThen(ClassTransform t) {
return new TransformImpl.ChainedClassTransform(this, t);
}
@Override
default ResolvedTransform<ClassElement> resolve(ClassBuilder builder) {
return new TransformImpl.ResolvedTransformImpl<>(e -> accept(builder, e),
() -> atEnd(builder),
() -> atStart(builder));
}
}

View File

@ -0,0 +1,652 @@
/*
* 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 jdk.internal.classfile;
import java.io.IOException;
import java.lang.constant.ClassDesc;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.UnknownAttribute;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ConstantPoolBuilder;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.ClassImpl;
import jdk.internal.classfile.impl.AbstractPoolEntry;
import jdk.internal.classfile.impl.DirectClassBuilder;
import jdk.internal.classfile.impl.Options;
import jdk.internal.classfile.impl.SplitConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.attribute.CharacterRangeInfo;
import jdk.internal.classfile.attribute.LocalVariableInfo;
import jdk.internal.classfile.attribute.LocalVariableTypeInfo;
import jdk.internal.classfile.instruction.ExceptionCatch;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
/**
* Main entry points for parsing, transforming, and generating classfiles.
*/
public class Classfile {
private Classfile() {
}
/**
* An option that affects the writing of classfiles.
*/
public sealed interface Option permits Options.OptionValue {
/**
* {@return an option describing whether or not to generate stackmaps}
* Default is to generate stack maps.
* @param b whether to generate stack maps
*/
static Option generateStackmap(boolean b) { return new Options.OptionValue(Options.Key.GENERATE_STACK_MAPS, b); }
/**
* {@return an option describing whether to process or discard debug elements}
* Debug elements include the local variable table, local variable type
* table, and character range table. Discarding debug elements may
* reduce the overhead of parsing or transforming classfiles.
* Default is to process debug elements.
* @param b whether or not to process debug elements
*/
static Option processDebug(boolean b) { return new Options.OptionValue(Options.Key.PROCESS_DEBUG, b); }
/**
* {@return an option describing whether to process or discard line numbers}
* Discarding line numbers may reduce the overhead of parsing or transforming
* classfiles.
* Default is to process line numbers.
* @param b whether or not to process line numbers
*/
static Option processLineNumbers(boolean b) { return new Options.OptionValue(Options.Key.PROCESS_LINE_NUMBERS, b); }
/**
* {@return an option describing whether to process or discard unrecognized
* attributes}
* Default is to process unrecognized attributes, and deliver as instances
* of {@link UnknownAttribute}.
* @param b whether or not to process unrecognized attributes
*/
static Option processUnknownAttributes(boolean b) { return new Options.OptionValue(Options.Key.PROCESS_UNKNOWN_ATTRIBUTES, b); }
/**
* {@return an option describing whether to preserve the original constant
* pool when transforming a classfile} Reusing the constant pool enables significant
* optimizations in processing time and minimizes differences between the
* original and transformed classfile, but may result in a bigger classfile
* when a classfile is significantly transformed.
* Default is to preserve the original constant pool.
* @param b whether or not to preserve the original constant pool
*/
static Option constantPoolSharing(boolean b) { return new Options.OptionValue(Options.Key.CP_SHARING, b); }
/**
* {@return an option describing whether or not to automatically rewrite
* short jumps to long when necessary}
* Default is to automatically rewrite jump instructions.
* @param b whether or not to automatically rewrite short jumps to long when necessary
*/
static Option fixShortJumps(boolean b) { return new Options.OptionValue(Options.Key.FIX_SHORT_JUMPS, b); }
/**
* {@return an option describing whether or not to patch out unreachable code}
* Default is to automatically patch out unreachable code with NOPs.
* @param b whether or not to automatically patch out unreachable code
*/
static Option patchDeadCode(boolean b) { return new Options.OptionValue(Options.Key.PATCH_DEAD_CODE, b); }
/**
* {@return an option describing the class hierarchy resolver to use when
* generating stack maps}
* @param r the resolver
*/
static Option classHierarchyResolver(ClassHierarchyResolver r) { return new Options.OptionValue(Options.Key.HIERARCHY_RESOLVER, r); }
/**
* {@return an option describing attribute mappers for custom attributes}
* Default is only to process standard attributes.
* @param r a function mapping attribute names to attribute mappers
*/
static Option attributeMapper(Function<Utf8Entry, AttributeMapper<?>> r) { return new Options.OptionValue(Options.Key.ATTRIBUTE_MAPPER, r); }
/**
* {@return an option describing whether or not to filter unresolved labels}
* Default is to throw IllegalStateException when any {@link ExceptionCatch},
* {@link LocalVariableInfo}, {@link LocalVariableTypeInfo}, or {@link CharacterRangeInfo}
* reference to unresolved {@link Label} during bytecode serialization.
* Setting this option to true filters the above elements instead.
* @param b whether or not to automatically patch out unreachable code
*/
static Option filterDeadLabels(boolean b) { return new Options.OptionValue(Options.Key.FILTER_DEAD_LABELS, b); }
}
/**
* Parse a classfile into a {@link ClassModel}.
* @param bytes the bytes of the classfile
* @param options the desired processing options
* @return the class model
*/
public static ClassModel parse(byte[] bytes, Option... options) {
Collection<Option> os = (options == null || options.length == 0)
? Collections.emptyList()
: List.of(options);
return new ClassImpl(bytes, os);
}
/**
* Parse a classfile into a {@link ClassModel}.
* @param path the path to the classfile
* @param options the desired processing options
* @return the class model
*/
public static ClassModel parse(Path path, Option... options) throws IOException {
return parse(Files.readAllBytes(path), options);
}
/**
* Build a classfile into a byte array.
* @param thisClass the name of the class to build
* @param handler a handler that receives a {@link ClassBuilder}
* @return the classfile bytes
*/
public static byte[] build(ClassDesc thisClass,
Consumer<ClassBuilder> handler) {
return build(thisClass, Collections.emptySet(), handler);
}
/**
* Build a classfile into a byte array.
* @param thisClass the name of the class to build
* @param options the desired processing options
* @param handler a handler that receives a {@link ClassBuilder}
* @return the classfile bytes
*/
public static byte[] build(ClassDesc thisClass,
Collection<Option> options,
Consumer<? super ClassBuilder> handler) {
ConstantPoolBuilder pool = ConstantPoolBuilder.of(options);
return build(pool.classEntry(thisClass), pool, handler);
}
/**
* Build a classfile into a byte array using the provided constant pool
* builder (which encapsulates classfile processing options.)
*
* @param thisClassEntry the name of the class to build
* @param constantPool the constant pool builder
* @param handler a handler that receives a {@link ClassBuilder}
* @return the classfile bytes
*/
public static byte[] build(ClassEntry thisClassEntry,
ConstantPoolBuilder constantPool,
Consumer<? super ClassBuilder> handler) {
thisClassEntry = AbstractPoolEntry.maybeClone(constantPool, thisClassEntry);
DirectClassBuilder builder = new DirectClassBuilder((SplitConstantPool)constantPool, thisClassEntry);
handler.accept(builder);
return builder.build();
}
/**
* Build a classfile into a file.
* @param path the path to the file to write
* @param thisClass the name of the class to build
* @param handler a handler that receives a {@link ClassBuilder}
*/
public static void buildTo(Path path,
ClassDesc thisClass,
Consumer<ClassBuilder> handler) throws IOException {
Files.write(path, build(thisClass, Collections.emptySet(), handler));
}
/**
* Build a classfile into a file.
* @param path the path to the file to write
* @param thisClass the name of the class to build
* @param options the desired processing options
* @param handler a handler that receives a {@link ClassBuilder}
*/
public static void buildTo(Path path,
ClassDesc thisClass,
Collection<Option> options,
Consumer<? super ClassBuilder> handler) throws IOException {
Files.write(path, build(thisClass, options, handler));
}
/**
* Build a module descriptor into a byte array.
* @param moduleAttribute the {@code Module} attribute
* @return the classfile bytes
*/
public static byte[] buildModule(ModuleAttribute moduleAttribute) {
return buildModule(moduleAttribute, List.of(), clb -> {});
}
/**
* Build a module descriptor into a byte array.
* @param moduleAttribute the {@code Module} attribute
* @param packages additional module packages
* @return the classfile bytes
*/
public static byte[] buildModule(ModuleAttribute moduleAttribute,
List<PackageDesc> packages) {
return buildModule(moduleAttribute, packages, clb -> {});
}
/**
* Build a module descriptor into a byte array.
* @param moduleAttribute the {@code Module} attribute
* @param packages additional module packages
* @param handler a handler that receives a {@link ClassBuilder}
* @return the classfile bytes
*/
public static byte[] buildModule(ModuleAttribute moduleAttribute,
List<PackageDesc> packages,
Consumer<? super ClassBuilder> handler) {
return build(ClassDesc.of("module-info"), clb -> {
clb.withFlags(AccessFlag.MODULE);
clb.with(moduleAttribute);
if (!packages.isEmpty()) {
var cp = clb.constantPool();
var allPackages = new LinkedHashSet<PackageEntry>();
for (var exp : moduleAttribute.exports()) allPackages.add(AbstractPoolEntry.maybeClone(cp, exp.exportedPackage()));
for (var opn : moduleAttribute.opens()) allPackages.add(AbstractPoolEntry.maybeClone(cp, opn.openedPackage()));
boolean emitMPA = false;
for (var p : packages)
emitMPA |= allPackages.add(cp.packageEntry(p));
if(emitMPA)
clb.with(new UnboundAttribute.UnboundModulePackagesAttribute(allPackages));
}
handler.accept(clb);
});
}
/**
* Build a module descriptor into a file.
* @param path the file to write
* @param moduleAttribute the {@code Module} attribute
*/
public static void buildModuleTo(Path path,
ModuleAttribute moduleAttribute) throws IOException {
buildModuleTo(path, moduleAttribute, List.of(), clb -> {});
}
/**
* Build a module descriptor into a file.
* @param path the file to write
* @param moduleAttribute the {@code Module} attribute
* @param packages additional module packages
*/
public static void buildModuleTo(Path path,
ModuleAttribute moduleAttribute,
List<PackageDesc> packages) throws IOException {
buildModuleTo(path, moduleAttribute, packages, clb -> {});
}
/**
* Build a module descriptor into a file.
* @param path the file to write
* @param moduleAttribute the {@code Module} attribute
* @param packages additional module packages
* @param handler a handler that receives a {@link ClassBuilder}
*/
public static void buildModuleTo(Path path,
ModuleAttribute moduleAttribute,
List<PackageDesc> packages,
Consumer<? super ClassBuilder> handler) throws IOException {
Files.write(path, buildModule(moduleAttribute, packages, handler));
}
public static final int MAGIC_NUMBER = 0xCAFEBABE;
public static final int NOP = 0;
public static final int ACONST_NULL = 1;
public static final int ICONST_M1 = 2;
public static final int ICONST_0 = 3;
public static final int ICONST_1 = 4;
public static final int ICONST_2 = 5;
public static final int ICONST_3 = 6;
public static final int ICONST_4 = 7;
public static final int ICONST_5 = 8;
public static final int LCONST_0 = 9;
public static final int LCONST_1 = 10;
public static final int FCONST_0 = 11;
public static final int FCONST_1 = 12;
public static final int FCONST_2 = 13;
public static final int DCONST_0 = 14;
public static final int DCONST_1 = 15;
public static final int BIPUSH = 16;
public static final int SIPUSH = 17;
public static final int LDC = 18;
public static final int LDC_W = 19;
public static final int LDC2_W = 20;
public static final int ILOAD = 21;
public static final int LLOAD = 22;
public static final int FLOAD = 23;
public static final int DLOAD = 24;
public static final int ALOAD = 25;
public static final int ILOAD_0 = 26;
public static final int ILOAD_1 = 27;
public static final int ILOAD_2 = 28;
public static final int ILOAD_3 = 29;
public static final int LLOAD_0 = 30;
public static final int LLOAD_1 = 31;
public static final int LLOAD_2 = 32;
public static final int LLOAD_3 = 33;
public static final int FLOAD_0 = 34;
public static final int FLOAD_1 = 35;
public static final int FLOAD_2 = 36;
public static final int FLOAD_3 = 37;
public static final int DLOAD_0 = 38;
public static final int DLOAD_1 = 39;
public static final int DLOAD_2 = 40;
public static final int DLOAD_3 = 41;
public static final int ALOAD_0 = 42;
public static final int ALOAD_1 = 43;
public static final int ALOAD_2 = 44;
public static final int ALOAD_3 = 45;
public static final int IALOAD = 46;
public static final int LALOAD = 47;
public static final int FALOAD = 48;
public static final int DALOAD = 49;
public static final int AALOAD = 50;
public static final int BALOAD = 51;
public static final int CALOAD = 52;
public static final int SALOAD = 53;
public static final int ISTORE = 54;
public static final int LSTORE = 55;
public static final int FSTORE = 56;
public static final int DSTORE = 57;
public static final int ASTORE = 58;
public static final int ISTORE_0 = 59;
public static final int ISTORE_1 = 60;
public static final int ISTORE_2 = 61;
public static final int ISTORE_3 = 62;
public static final int LSTORE_0 = 63;
public static final int LSTORE_1 = 64;
public static final int LSTORE_2 = 65;
public static final int LSTORE_3 = 66;
public static final int FSTORE_0 = 67;
public static final int FSTORE_1 = 68;
public static final int FSTORE_2 = 69;
public static final int FSTORE_3 = 70;
public static final int DSTORE_0 = 71;
public static final int DSTORE_1 = 72;
public static final int DSTORE_2 = 73;
public static final int DSTORE_3 = 74;
public static final int ASTORE_0 = 75;
public static final int ASTORE_1 = 76;
public static final int ASTORE_2 = 77;
public static final int ASTORE_3 = 78;
public static final int IASTORE = 79;
public static final int LASTORE = 80;
public static final int FASTORE = 81;
public static final int DASTORE = 82;
public static final int AASTORE = 83;
public static final int BASTORE = 84;
public static final int CASTORE = 85;
public static final int SASTORE = 86;
public static final int POP = 87;
public static final int POP2 = 88;
public static final int DUP = 89;
public static final int DUP_X1 = 90;
public static final int DUP_X2 = 91;
public static final int DUP2 = 92;
public static final int DUP2_X1 = 93;
public static final int DUP2_X2 = 94;
public static final int SWAP = 95;
public static final int IADD = 96;
public static final int LADD = 97;
public static final int FADD = 98;
public static final int DADD = 99;
public static final int ISUB = 100;
public static final int LSUB = 101;
public static final int FSUB = 102;
public static final int DSUB = 103;
public static final int IMUL = 104;
public static final int LMUL = 105;
public static final int FMUL = 106;
public static final int DMUL = 107;
public static final int IDIV = 108;
public static final int LDIV = 109;
public static final int FDIV = 110;
public static final int DDIV = 111;
public static final int IREM = 112;
public static final int LREM = 113;
public static final int FREM = 114;
public static final int DREM = 115;
public static final int INEG = 116;
public static final int LNEG = 117;
public static final int FNEG = 118;
public static final int DNEG = 119;
public static final int ISHL = 120;
public static final int LSHL = 121;
public static final int ISHR = 122;
public static final int LSHR = 123;
public static final int IUSHR = 124;
public static final int LUSHR = 125;
public static final int IAND = 126;
public static final int LAND = 127;
public static final int IOR = 128;
public static final int LOR = 129;
public static final int IXOR = 130;
public static final int LXOR = 131;
public static final int IINC = 132;
public static final int I2L = 133;
public static final int I2F = 134;
public static final int I2D = 135;
public static final int L2I = 136;
public static final int L2F = 137;
public static final int L2D = 138;
public static final int F2I = 139;
public static final int F2L = 140;
public static final int F2D = 141;
public static final int D2I = 142;
public static final int D2L = 143;
public static final int D2F = 144;
public static final int I2B = 145;
public static final int I2C = 146;
public static final int I2S = 147;
public static final int LCMP = 148;
public static final int FCMPL = 149;
public static final int FCMPG = 150;
public static final int DCMPL = 151;
public static final int DCMPG = 152;
public static final int IFEQ = 153;
public static final int IFNE = 154;
public static final int IFLT = 155;
public static final int IFGE = 156;
public static final int IFGT = 157;
public static final int IFLE = 158;
public static final int IF_ICMPEQ = 159;
public static final int IF_ICMPNE = 160;
public static final int IF_ICMPLT = 161;
public static final int IF_ICMPGE = 162;
public static final int IF_ICMPGT = 163;
public static final int IF_ICMPLE = 164;
public static final int IF_ACMPEQ = 165;
public static final int IF_ACMPNE = 166;
public static final int GOTO = 167;
public static final int JSR = 168;
public static final int RET = 169;
public static final int TABLESWITCH = 170;
public static final int LOOKUPSWITCH = 171;
public static final int IRETURN = 172;
public static final int LRETURN = 173;
public static final int FRETURN = 174;
public static final int DRETURN = 175;
public static final int ARETURN = 176;
public static final int RETURN = 177;
public static final int GETSTATIC = 178;
public static final int PUTSTATIC = 179;
public static final int GETFIELD = 180;
public static final int PUTFIELD = 181;
public static final int INVOKEVIRTUAL = 182;
public static final int INVOKESPECIAL = 183;
public static final int INVOKESTATIC = 184;
public static final int INVOKEINTERFACE = 185;
public static final int INVOKEDYNAMIC = 186;
public static final int NEW = 187;
public static final int NEWARRAY = 188;
public static final int ANEWARRAY = 189;
public static final int ARRAYLENGTH = 190;
public static final int ATHROW = 191;
public static final int CHECKCAST = 192;
public static final int INSTANCEOF = 193;
public static final int MONITORENTER = 194;
public static final int MONITOREXIT = 195;
public static final int WIDE = 196;
public static final int MULTIANEWARRAY = 197;
public static final int IFNULL = 198;
public static final int IFNONNULL = 199;
public static final int GOTO_W = 200;
public static final int JSR_W = 201;
public static final int ACC_PUBLIC = 0x0001;
public static final int ACC_PROTECTED = 0x0004;
public static final int ACC_PRIVATE = 0x0002;
public static final int ACC_INTERFACE = 0x0200;
public static final int ACC_ENUM = 0x4000;
public static final int ACC_ANNOTATION = 0x2000;
public static final int ACC_SUPER = 0x0020;
public static final int ACC_ABSTRACT = 0x0400;
public static final int ACC_VOLATILE = 0x0040;
public static final int ACC_TRANSIENT = 0x0080;
public static final int ACC_SYNTHETIC = 0x1000;
public static final int ACC_STATIC = 0x0008;
public static final int ACC_FINAL = 0x0010;
public static final int ACC_SYNCHRONIZED = 0x0020;
public static final int ACC_BRIDGE = 0x0040;
public static final int ACC_VARARGS = 0x0080;
public static final int ACC_NATIVE = 0x0100;
public static final int ACC_STRICT = 0x0800;
public static final int ACC_MODULE = 0x8000;
public static final int ACC_OPEN = 0x20;
public static final int ACC_MANDATED = 0x8000;
public static final int ACC_TRANSITIVE = 0x20;
public static final int ACC_STATIC_PHASE = 0x40;
public static final int CRT_STATEMENT = 0x0001;
public static final int CRT_BLOCK = 0x0002;
public static final int CRT_ASSIGNMENT = 0x0004;
public static final int CRT_FLOW_CONTROLLER = 0x0008;
public static final int CRT_FLOW_TARGET = 0x0010;
public static final int CRT_INVOKE = 0x0020;
public static final int CRT_CREATE = 0x0040;
public static final int CRT_BRANCH_TRUE = 0x0080;
public static final int CRT_BRANCH_FALSE = 0x0100;
public static final int TAG_CLASS = 7;
public static final int TAG_CONSTANTDYNAMIC = 17;
public static final int TAG_DOUBLE = 6;
public static final int TAG_FIELDREF = 9;
public static final int TAG_FLOAT = 4;
public static final int TAG_INTEGER = 3;
public static final int TAG_INTERFACEMETHODREF = 11;
public static final int TAG_INVOKEDYNAMIC = 18;
public static final int TAG_LONG = 5;
public static final int TAG_METHODHANDLE = 15;
public static final int TAG_METHODREF = 10;
public static final int TAG_METHODTYPE = 16;
public static final int TAG_MODULE = 19;
public static final int TAG_NAMEANDTYPE = 12;
public static final int TAG_PACKAGE = 20;
public static final int TAG_STRING = 8;
public static final int TAG_UNICODE = 2;
public static final int TAG_UTF8 = 1;
//type annotations
public static final int TAT_CLASS_TYPE_PARAMETER = 0x00;
public static final int TAT_METHOD_TYPE_PARAMETER = 0x01;
public static final int TAT_CLASS_EXTENDS = 0x10;
public static final int TAT_CLASS_TYPE_PARAMETER_BOUND = 0x11;
public static final int TAT_METHOD_TYPE_PARAMETER_BOUND = 0x12;
public static final int TAT_FIELD = 0x13;
public static final int TAT_METHOD_RETURN = 0x14;
public static final int TAT_METHOD_RECEIVER = 0x15;
public static final int TAT_METHOD_FORMAL_PARAMETER = 0x16;
public static final int TAT_THROWS = 0x17;
public static final int TAT_LOCAL_VARIABLE = 0x40;
public static final int TAT_RESOURCE_VARIABLE = 0x41;
public static final int TAT_EXCEPTION_PARAMETER = 0x42;
public static final int TAT_INSTANCEOF = 0x43;
public static final int TAT_NEW = 0x44;
public static final int TAT_CONSTRUCTOR_REFERENCE = 0x45;
public static final int TAT_METHOD_REFERENCE = 0x46;
public static final int TAT_CAST = 0x47;
public static final int TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
public static final int TAT_METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
public static final int TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
public static final int TAT_METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
//stackmap verification types
public static final int VT_TOP = 0;
public static final int VT_INTEGER = 1;
public static final int VT_FLOAT = 2;
public static final int VT_DOUBLE = 3;
public static final int VT_LONG = 4;
public static final int VT_NULL = 5;
public static final int VT_UNINITIALIZED_THIS = 6;
public static final int VT_OBJECT = 7;
public static final int VT_UNINITIALIZED = 8;
public static final int DEFAULT_CLASS_FLAGS = ACC_PUBLIC;
public static final int JAVA_1_VERSION = 45;
public static final int JAVA_2_VERSION = 46;
public static final int JAVA_3_VERSION = 47;
public static final int JAVA_4_VERSION = 48;
public static final int JAVA_5_VERSION = 49;
public static final int JAVA_6_VERSION = 50;
public static final int JAVA_7_VERSION = 51;
public static final int JAVA_8_VERSION = 52;
public static final int JAVA_9_VERSION = 53;
public static final int JAVA_10_VERSION = 54;
public static final int JAVA_11_VERSION = 55;
public static final int JAVA_12_VERSION = 56;
public static final int JAVA_13_VERSION = 57;
public static final int JAVA_14_VERSION = 58;
public static final int JAVA_15_VERSION = 59;
public static final int JAVA_16_VERSION = 60;
public static final int JAVA_17_VERSION = 61;
public static final int JAVA_18_VERSION = 62;
public static final int JAVA_19_VERSION = 63;
public static final int JAVA_20_VERSION = 64;
public static final int JAVA_21_VERSION = 65;
public static final int LATEST_MAJOR_VERSION = JAVA_21_VERSION;
public static final int LATEST_MINOR_VERSION = 0;
public static final int PREVIEW_MINOR_VERSION = -1;
}

View File

@ -0,0 +1,89 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import java.util.function.Consumer;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.constantpool.ConstantPoolBuilder;
/**
* A builder for a classfile or portion of a classfile. Builders are rarely
* created directly; they are passed to handlers by methods such as
* {@link Classfile#build(ClassDesc, Consumer)} or to transforms.
* Elements of the newly built entity can be specified
* abstractly (by passing a {@link ClassfileElement} to {@link #with(ClassfileElement)}
* or concretely by calling the various {@code withXxx} methods.
*
* @see ClassfileTransform
*/
public
interface ClassfileBuilder<E extends ClassfileElement, B extends ClassfileBuilder<E, B>>
extends Consumer<E> {
/**
* Integrate the {@link ClassfileElement} into the entity being built.
* @param e the element
*/
@Override
default void accept(E e) {
with(e);
}
/**
* Integrate the {@link ClassfileElement} into the entity being built.
* @param e the element
* @return this builder
*/
B with(E e);
/**
* {@return the constant pool builder associated with this builder}
*/
ConstantPoolBuilder constantPool();
/**
* {@return whether the provided constant pool is compatible with this builder}
* @param source the constant pool to test compatibility with
*/
default boolean canWriteDirect(ConstantPool source) {
return constantPool().canWriteDirect(source);
}
/**
* Apply a transform to a model, directing results to this builder.
* @param model the model to transform
* @param transform the transform to apply
*/
default void transform(CompoundElement<E> model, ClassfileTransform<?, E, B> transform) {
@SuppressWarnings("unchecked")
B builder = (B) this;
var resolved = transform.resolve(builder);
resolved.startHandler().run();
model.forEachElement(resolved.consumer());
resolved.endHandler().run();
}
}

View File

@ -0,0 +1,38 @@
/*
* 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 jdk.internal.classfile;
/**
* Immutable model for a portion of (or the entirety of) a classfile. Elements
* that model parts of the classfile that have attributes will implement {@link
* AttributedElement}; elements that model complex parts of the classfile that
* themselves contain their own child elements will implement {@link
* CompoundElement}. Elements specific to various locations in the classfile
* will implement {@link ClassElement}, {@link MethodElement}, etc.
*/
public sealed interface ClassfileElement
permits AttributedElement, CompoundElement, WritableElement,
ClassElement, CodeElement, FieldElement, MethodElement {
}

View File

@ -0,0 +1,158 @@
/*
* 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 jdk.internal.classfile;
import java.util.function.Consumer;
import java.util.function.Supplier;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
/**
* A transformation on streams of elements. Transforms are used during
* transformation of classfile entities; a transform is provided to a method like
* {@link ClassModel#transform(ClassTransform)}, and the elements of the class,
* along with a builder, are presented to the transform.
*
* <p>The subtypes of {@linkplain
* ClassfileTransform} (e.g., {@link ClassTransform}) are functional interfaces
* that accept an element and a corresponding builder. Since any element can be
* reproduced on the builder via {@link ClassBuilder#with(ClassfileElement)}, a
* transform can easily leave elements in place, remove them, replace them, or
* augment them with other elements. This enables localized transforms to be
* represented concisely.
*
* <p>Transforms also have an {@link #atEnd(ClassfileBuilder)} method, for
* which the default implementation does nothing, so that a transform can
* perform additional building after the stream of elements is exhausted.
*
* <p>Transforms can be chained together via the {@link
* #andThen(ClassfileTransform)} method, so that the output of one becomes the
* input to another. This allows smaller units of transformation to be captured
* and reused.
*
* <p>Some transforms are stateful; for example, a transform that injects an
* annotation on a class may watch for the {@link RuntimeVisibleAnnotationsAttribute}
* element and transform it if found, but if it is not found, will generate a
* {@linkplain RuntimeVisibleAnnotationsAttribute} element containing the
* injected annotation from the {@linkplain #atEnd(ClassfileBuilder)} handler.
* To do this, the transform must accumulate some state during the traversal so
* that the end handler knows what to do. If such a transform is to be reused,
* its state must be reset for each traversal; this will happen automatically if
* the transform is created with {@link ClassTransform#ofStateful(Supplier)} (or
* corresponding methods for other classfile locations.)
* <p>
* Class transformation sample where code transformation is stateful:
* {@snippet lang="java" class="PackageSnippets" region="codeRelabeling"}
* <p>
* Complex class instrumentation sample chaining multiple transformations:
* {@snippet lang="java" class="PackageSnippets" region="classInstrumentation"}
*/
public sealed interface ClassfileTransform<
C extends ClassfileTransform<C, E, B>,
E extends ClassfileElement,
B extends ClassfileBuilder<E, B>>
permits ClassTransform, FieldTransform, MethodTransform, CodeTransform {
/**
* Transform an element by taking the appropriate actions on the builder.
* Used when transforming a classfile entity (class, method, field, method
* body.) If no transformation is desired, the element can be presented to
* {@link B#with(ClassfileElement)}. If the element is to be dropped, no
* action is required.
*
* @param builder the builder for the new entity
* @param element the element
*/
void accept(B builder, E element);
/**
* Take any final action during transformation of a classfile entity. Called
* after all elements of the class are presented to {@link
* #accept(ClassfileBuilder, ClassfileElement)}.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
*/
default void atEnd(B builder) {
}
/**
* Take any preliminary action during transformation of a classfile entity.
* Called before any elements of the class are presented to {@link
* #accept(ClassfileBuilder, ClassfileElement)}.
*
* @param builder the builder for the new entity
* @implSpec The default implementation does nothing.
*/
default void atStart(B builder) {
}
/**
* Chain this transform with another; elements presented to the builder of
* this transform will become the input to the next transform.
*
* @param next the downstream transform
* @return the chained transform
*/
C andThen(C next);
/**
* The result of binding a transform to a builder. Used primarily within
* the implementation to perform transformation.
*
* @param <E> the element type
*/
interface ResolvedTransform<E extends ClassfileElement> {
/**
* {@return a {@link Consumer} to receive elements}
*/
Consumer<E> consumer();
/**
* {@return an action to call at the end of transformation}
*/
Runnable endHandler();
/**
* {@return an action to call at the start of transformation}
*/
Runnable startHandler();
}
/**
* Bind a transform to a builder. If the transform is chained, intermediate
* builders are created for each chain link. If the transform is stateful
* (see, e.g., {@link ClassTransform#ofStateful(Supplier)}), the supplier is
* invoked to get a fresh transform object.
*
* <p>This method is a low-level method that should rarely be used by
* user code; most of the time, user code should prefer
* {@link ClassfileBuilder#transform(CompoundElement, ClassfileTransform)},
* which resolves the transform and executes it on the current builder.
*
* @param builder the builder to bind to
* @return the bound result
*/
ResolvedTransform<E> resolve(B builder);
}

View File

@ -0,0 +1,55 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.impl.ClassfileVersionImpl;
/**
* Models the classfile version information for a class. Delivered as a {@link
* jdk.internal.classfile.ClassElement} when traversing the elements of a {@link
* ClassModel}.
*/
public sealed interface ClassfileVersion
extends ClassElement
permits ClassfileVersionImpl {
/**
* {@return the major classfile version}
*/
int majorVersion();
/**
* {@return the minor classfile version}
*/
int minorVersion();
/**
* {@return a {@link ClassfileVersion} element}
* @param majorVersion the major classfile version
* @param minorVersion the minor classfile version
*/
static ClassfileVersion of(int majorVersion, int minorVersion) {
return new ClassfileVersionImpl(majorVersion, minorVersion);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.StackMapTableAttribute;
/**
* A {@link ClassfileElement} that can appear when traversing the elements
* of a {@link CodeModel} or be presented to a {@link CodeBuilder}. Code elements
* are either an {@link Instruction}, which models an instruction in the body
* of a method, or a {@link PseudoInstruction}, which models metadata from
* the code attribute, such as line number metadata, local variable metadata,
* exception metadata, label target metadata, etc.
*/
public sealed interface CodeElement extends ClassfileElement
permits Instruction, PseudoInstruction,
CustomAttribute, RuntimeVisibleTypeAnnotationsAttribute, RuntimeInvisibleTypeAnnotationsAttribute,
StackMapTableAttribute {
}

View File

@ -0,0 +1,65 @@
/*
* 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 jdk.internal.classfile;
import java.util.List;
import java.util.Optional;
import jdk.internal.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.impl.BufferedCodeBuilder;
import jdk.internal.classfile.impl.CodeImpl;
import jdk.internal.classfile.instruction.ExceptionCatch;
/**
* Models the body of a method (the {@code Code} attribute). The instructions
* of the method body are accessed via a streaming view (e.g., {@link
* #elements()}).
*/
public sealed interface CodeModel
extends CompoundElement<CodeElement>, AttributedElement, MethodElement
permits CodeAttribute, BufferedCodeBuilder.Model, CodeImpl {
/**
* {@return the maximum size of the local variable table}
*/
int maxLocals();
/**
* {@return the maximum size of the operand stack}
*/
int maxStack();
/**
* {@return the enclosing method, if known}
*/
Optional<MethodModel> parent();
/**
* {@return the exception table of the method} The exception table is also
* modeled by {@link ExceptionCatch} elements in the streaming view.
*/
List<ExceptionCatch> exceptionHandlers();
}

View File

@ -0,0 +1,95 @@
/*
* 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 jdk.internal.classfile;
import java.util.function.Consumer;
import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A transformation on streams of {@link CodeElement}.
*
* @see ClassfileTransform
*/
@FunctionalInterface
public non-sealed interface CodeTransform
extends ClassfileTransform<CodeTransform, CodeElement, CodeBuilder> {
/**
* A code transform that sends all elements to the builder.
*/
CodeTransform ACCEPT_ALL = new CodeTransform() {
@Override
public void accept(CodeBuilder builder, CodeElement element) {
builder.with(element);
}
};
/**
* Create a stateful code transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
* for each traversal
* @return the stateful code transform
*/
static CodeTransform ofStateful(Supplier<CodeTransform> supplier) {
return new TransformImpl.SupplierCodeTransform(supplier);
}
/**
* Create a code transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
* @return the code transform
*/
static CodeTransform endHandler(Consumer<CodeBuilder> finisher) {
return new CodeTransform() {
@Override
public void accept(CodeBuilder builder, CodeElement element) {
builder.with(element);
}
@Override
public void atEnd(CodeBuilder builder) {
finisher.accept(builder);
}
};
}
@Override
default CodeTransform andThen(CodeTransform t) {
return new TransformImpl.ChainedCodeTransform(this, t);
}
@Override
default ResolvedTransform<CodeElement> resolve(CodeBuilder builder) {
return new TransformImpl.ResolvedTransformImpl<>(e -> accept(builder, e),
() -> atEnd(builder),
() -> atStart(builder));
}
}

View File

@ -0,0 +1,97 @@
/*
* 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 jdk.internal.classfile;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* A {@link ClassfileElement} that has complex structure defined in terms of
* other classfile elements, such as a method, field, method body, or entire
* class. When encountering a {@linkplain CompoundElement}, clients have the
* option to treat the element as a single entity (e.g., an entire method)
* or to traverse the contents of that element with the methods in this class
* (e.g., {@link #elements()}, {@link #forEachElement(Consumer)}, etc.)
*/
public sealed interface CompoundElement<E extends ClassfileElement>
extends ClassfileElement, Iterable<E>
permits ClassModel, CodeModel, FieldModel, MethodModel, jdk.internal.classfile.impl.AbstractUnboundModel {
/**
* Invoke the provided handler with each element contained in this
* compound element
* @param consumer the handler
*/
void forEachElement(Consumer<E> consumer);
/**
* {@return an {@link Iterable} describing all the elements contained in this
* compound element}
*/
default Iterable<E> elements() {
return elementList();
}
/**
* {@return an {@link Iterator} describing all the elements contained in this
* compound element}
*/
@Override
default Iterator<E> iterator() {
return elements().iterator();
}
/**
* {@return a {@link Stream} containing all the elements contained in this
* compound element}
*/
default Stream<E> elementStream() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iterator(),
Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED),
false);
}
/**
* {@return an {@link List} containing all the elements contained in this
* compound element}
*/
default List<E> elementList() {
List<E> list = new ArrayList<>();
forEachElement(new Consumer<>() {
@Override
public void accept(E e) {
list.add(e);
}
});
return list;
}
}

View File

@ -0,0 +1,47 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a non-standard attribute of a classfile. Clients should extend
* this class to provide an implementation class for non-standard attributes,
* and provide an {@link AttributeMapper} to mediate between the classfile
* format and the {@linkplain CustomAttribute} representation.
*/
@SuppressWarnings("exports")
public abstract non-sealed class CustomAttribute<T extends CustomAttribute<T>>
extends UnboundAttribute.CustomAttribute<T>
implements CodeElement, ClassElement, MethodElement, FieldElement {
/**
* Construct a {@linkplain CustomAttribute}.
* @param mapper the attribute mapper
*/
protected CustomAttribute(AttributeMapper<T> mapper) {
super(mapper);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.ChainedFieldBuilder;
import jdk.internal.classfile.impl.TerminalFieldBuilder;
import java.lang.reflect.AccessFlag;
import java.util.Optional;
import java.util.function.Consumer;
/**
* A builder for fields. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withField(Utf8Entry, Utf8Entry, Consumer)}
* or to field transforms. The elements of a field can be specified
* abstractly (by passing a {@link FieldElement} to {@link #with(ClassfileElement)}
* or concretely by calling the various {@code withXxx} methods.
*
* @see FieldTransform
*/
public sealed interface FieldBuilder
extends ClassfileBuilder<FieldElement, FieldBuilder>
permits TerminalFieldBuilder, ChainedFieldBuilder {
/**
* Sets the field access flags.
* @param flags the access flags, as a bit mask
* @return this builder
*/
default FieldBuilder withFlags(int flags) {
return with(AccessFlags.ofField(flags));
}
/**
* Sets the field access flags.
* @param flags the access flags, as a bit mask
* @return this builder
*/
default FieldBuilder withFlags(AccessFlag... flags) {
return with(AccessFlags.ofField(flags));
}
/**
* {@return the {@link FieldModel} representing the field being transformed,
* if this field builder represents the transformation of some {@link FieldModel}}
*/
Optional<FieldModel> original();
}

View File

@ -0,0 +1,48 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.ConstantValueAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.SignatureAttribute;
import jdk.internal.classfile.attribute.SyntheticAttribute;
import jdk.internal.classfile.attribute.UnknownAttribute;
/**
* A {@link ClassfileElement} that can appear when traversing the elements
* of a {@link FieldModel} or be presented to a {@link FieldBuilder}.
*/
public sealed interface FieldElement extends ClassfileElement
permits AccessFlags,
CustomAttribute, ConstantValueAttribute, DeprecatedAttribute,
RuntimeInvisibleAnnotationsAttribute, RuntimeInvisibleTypeAnnotationsAttribute,
RuntimeVisibleAnnotationsAttribute, RuntimeVisibleTypeAnnotationsAttribute,
SignatureAttribute, SyntheticAttribute, UnknownAttribute {
}

View File

@ -0,0 +1,60 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import java.util.Optional;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BufferedFieldBuilder;
import jdk.internal.classfile.impl.FieldImpl;
/**
* Models a field. The contents of the field can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*/
public sealed interface FieldModel
extends WritableElement<FieldModel>, CompoundElement<FieldElement>, AttributedElement, ClassElement
permits BufferedFieldBuilder.Model, FieldImpl {
/** {@return the access flags} */
AccessFlags flags();
/** {@return the class model this field is a member of, if known} */
Optional<ClassModel> parent();
/** {@return the name of this field} */
Utf8Entry fieldName();
/** {@return the field descriptor of this field} */
Utf8Entry fieldType();
/** {@return the field descriptor of this field, as a symbolic descriptor} */
default ClassDesc fieldTypeSymbol() {
return ClassDesc.ofDescriptor(fieldType().stringValue());
}
}

View File

@ -0,0 +1,110 @@
/*
* 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 jdk.internal.classfile;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A transformation on streams of {@link FieldElement}.
*
* @see ClassfileTransform
*/
@FunctionalInterface
public non-sealed interface FieldTransform
extends ClassfileTransform<FieldTransform, FieldElement, FieldBuilder> {
/**
* A field transform that sends all elements to the builder.
*/
FieldTransform ACCEPT_ALL = new FieldTransform() {
@Override
public void accept(FieldBuilder builder, FieldElement element) {
builder.with(element);
}
};
/**
* Create a stateful field transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
* for each traversal
* @return the stateful field transform
*/
static FieldTransform ofStateful(Supplier<FieldTransform> supplier) {
return new TransformImpl.SupplierFieldTransform(supplier);
}
/**
* Create a field transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
* @return the field transform
*/
static FieldTransform endHandler(Consumer<FieldBuilder> finisher) {
return new FieldTransform() {
@Override
public void accept(FieldBuilder builder, FieldElement element) {
builder.with(element);
}
@Override
public void atEnd(FieldBuilder builder) {
finisher.accept(builder);
}
};
}
/**
* Create a field transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop
* @return the field transform
*/
static FieldTransform dropping(Predicate<FieldElement> filter) {
return (b, e) -> {
if (!filter.test(e))
b.with(e);
};
}
@Override
default FieldTransform andThen(FieldTransform t) {
return new TransformImpl.ChainedFieldTransform(this, t);
}
@Override
default ResolvedTransform<FieldElement> resolve(FieldBuilder builder) {
return new TransformImpl.ResolvedTransformImpl<>(e -> accept(builder, e),
() -> atEnd(builder),
() -> atStart(builder));
}
}

View File

@ -0,0 +1,77 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.instruction.ArrayLoadInstruction;
import jdk.internal.classfile.instruction.ArrayStoreInstruction;
import jdk.internal.classfile.instruction.BranchInstruction;
import jdk.internal.classfile.instruction.ConstantInstruction;
import jdk.internal.classfile.instruction.ConvertInstruction;
import jdk.internal.classfile.instruction.FieldInstruction;
import jdk.internal.classfile.instruction.IncrementInstruction;
import jdk.internal.classfile.instruction.InvokeDynamicInstruction;
import jdk.internal.classfile.instruction.InvokeInstruction;
import jdk.internal.classfile.instruction.LoadInstruction;
import jdk.internal.classfile.instruction.LookupSwitchInstruction;
import jdk.internal.classfile.instruction.MonitorInstruction;
import jdk.internal.classfile.instruction.NewMultiArrayInstruction;
import jdk.internal.classfile.instruction.NewObjectInstruction;
import jdk.internal.classfile.instruction.NewPrimitiveArrayInstruction;
import jdk.internal.classfile.instruction.NewReferenceArrayInstruction;
import jdk.internal.classfile.instruction.NopInstruction;
import jdk.internal.classfile.instruction.OperatorInstruction;
import jdk.internal.classfile.instruction.ReturnInstruction;
import jdk.internal.classfile.instruction.StackInstruction;
import jdk.internal.classfile.instruction.StoreInstruction;
import jdk.internal.classfile.instruction.TableSwitchInstruction;
import jdk.internal.classfile.instruction.ThrowInstruction;
import jdk.internal.classfile.instruction.TypeCheckInstruction;
/**
* Models an executable instruction in a method body.
*/
public sealed interface Instruction extends CodeElement
permits ArrayLoadInstruction, ArrayStoreInstruction, BranchInstruction,
ConstantInstruction, ConvertInstruction, FieldInstruction,
InvokeDynamicInstruction, InvokeInstruction, LoadInstruction,
StoreInstruction, IncrementInstruction,
LookupSwitchInstruction, MonitorInstruction, NewMultiArrayInstruction,
NewObjectInstruction, NewPrimitiveArrayInstruction, NewReferenceArrayInstruction,
NopInstruction, OperatorInstruction, ReturnInstruction,
StackInstruction, TableSwitchInstruction,
ThrowInstruction, TypeCheckInstruction, AbstractInstruction {
/**
* {@return the opcode of this instruction}
*/
Opcode opcode();
/**
* {@return the size in bytes of this instruction}
*/
int sizeInBytes();
}

View File

@ -0,0 +1,77 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.InterfacesImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models the interfaces of a class. Delivered as a {@link
* jdk.internal.classfile.ClassElement} when traversing a {@link ClassModel}.
*/
public sealed interface Interfaces
extends ClassElement
permits InterfacesImpl {
/** {@return the interfaces of this class} */
List<ClassEntry> interfaces();
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
*/
static Interfaces of(List<ClassEntry> interfaces) {
return new InterfacesImpl(interfaces);
}
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
*/
static Interfaces of(ClassEntry... interfaces) {
return of(List.of(interfaces));
}
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
*/
static Interfaces ofSymbols(List<ClassDesc> interfaces) {
return of(Util.entryList(interfaces));
}
/**
* {@return an {@linkplain Interfaces} element}
* @param interfaces the interfaces
*/
static Interfaces ofSymbols(ClassDesc... interfaces) {
return ofSymbols(Arrays.asList(interfaces));
}
}

View File

@ -0,0 +1,44 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.impl.LabelImpl;
/**
* A marker for a position within the instructions of a method body. The
* assocation between a label's identity and the position it represents is
* managed by the entity managing the method body (a {@link CodeModel} or {@link
* CodeBuilder}), not the label itself; this allows the same label to have a
* meaning both in an existing method (as managed by a {@linkplain CodeModel})
* and in the transformation of that method (as managed by a {@linkplain
* CodeBuilder}), while corresponding to different positions in each. When
* traversing the elements of a {@linkplain CodeModel}, {@linkplain Label}
* markers will be delivered at the position to which they correspond. A label
* can be bound to the current position within a {@linkplain CodeBuilder} via
* {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassfileElement)}.
*/
public sealed interface Label
permits LabelImpl {
}

View File

@ -0,0 +1,95 @@
/*
* 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 jdk.internal.classfile;
import java.util.Optional;
import java.util.function.Consumer;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.ChainedMethodBuilder;
import jdk.internal.classfile.impl.TerminalMethodBuilder;
import java.lang.reflect.AccessFlag;
/**
* A builder for methods. Builders are not created directly; they are passed
* to handlers by methods such as {@link ClassBuilder#withMethod(Utf8Entry, Utf8Entry, int, Consumer)}
* or to method transforms. The elements of a method can be specified
* abstractly (by passing a {@link MethodElement} to {@link #with(ClassfileElement)}
* or concretely by calling the various {@code withXxx} methods.
*
* @see MethodTransform
*/
public sealed interface MethodBuilder
extends ClassfileBuilder<MethodElement, MethodBuilder>
permits ChainedMethodBuilder, TerminalMethodBuilder {
/**
* {@return the {@link MethodModel} representing the method being transformed,
* if this method builder represents the transformation of some {@link MethodModel}}
*/
Optional<MethodModel> original();
/**
* Sets the method access flags.
* @param flags the access flags, as a bit mask
* @return this builder
*/
default MethodBuilder withFlags(int flags) {
return with(AccessFlags.ofMethod(flags));
}
/**
* Sets the method access flags.
* @param flags the access flags, as a bit mask
* @return this builder
*/
default MethodBuilder withFlags(AccessFlag... flags) {
return with(AccessFlags.ofMethod(flags));
}
/**
* Build the method body for this method.
* @param code a handler receiving a {@link CodeBuilder}
* @return this builder
*/
MethodBuilder withCode(Consumer<? super CodeBuilder> code);
/**
* Build the method body for this method by transforming the body of another
* method.
*
* @implNote
* <p>This method behaves as if:
* {@snippet lang=java :
* withCode(b -> b.transformCode(code, transform));
* }
*
* @param code the method body to be transformed
* @param transform the transform to apply to the method body
* @return this builder
*/
MethodBuilder transformCode(CodeModel code, CodeTransform transform);
}

View File

@ -0,0 +1,55 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.AnnotationDefaultAttribute;
import jdk.internal.classfile.attribute.DeprecatedAttribute;
import jdk.internal.classfile.attribute.ExceptionsAttribute;
import jdk.internal.classfile.attribute.MethodParametersAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.SignatureAttribute;
import jdk.internal.classfile.attribute.SyntheticAttribute;
import jdk.internal.classfile.attribute.UnknownAttribute;
/**
* A {@link ClassfileElement} that can appear when traversing the elements
* of a {@link MethodModel} or be presented to a {@link MethodBuilder}.
*/
public sealed interface MethodElement
extends ClassfileElement
permits AccessFlags, CodeModel, CustomAttribute,
AnnotationDefaultAttribute, DeprecatedAttribute,
ExceptionsAttribute, MethodParametersAttribute,
RuntimeInvisibleAnnotationsAttribute, RuntimeInvisibleParameterAnnotationsAttribute,
RuntimeInvisibleTypeAnnotationsAttribute, RuntimeVisibleAnnotationsAttribute,
RuntimeVisibleParameterAnnotationsAttribute, RuntimeVisibleTypeAnnotationsAttribute,
SignatureAttribute, SyntheticAttribute, UnknownAttribute {
}

View File

@ -0,0 +1,63 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.MethodTypeDesc;
import java.util.Optional;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BufferedMethodBuilder;
import jdk.internal.classfile.impl.MethodImpl;
/**
* Models a method. The contents of the method can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*/
public sealed interface MethodModel
extends WritableElement<MethodModel>, CompoundElement<MethodElement>, AttributedElement, ClassElement
permits BufferedMethodBuilder.Model, MethodImpl {
/** {@return the access flags} */
AccessFlags flags();
/** {@return the class model this method is a member of, if known} */
Optional<ClassModel> parent();
/** {@return the name of this method} */
Utf8Entry methodName();
/** {@return the method descriptor of this method} */
Utf8Entry methodType();
/** {@return the method descriptor of this method, as a symbolic descriptor} */
default MethodTypeDesc methodTypeSymbol() {
return MethodTypeDesc.ofDescriptor(methodType().stringValue());
}
/** {@return the body of this method, if there is one} */
Optional<CodeModel> code();
}

View File

@ -0,0 +1,110 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.MethodTypeDesc;
import java.util.List;
import jdk.internal.classfile.impl.SignaturesImpl;
import static java.util.Objects.requireNonNull;
import jdk.internal.classfile.impl.Util;
/**
* Models the generic signature of a method, as defined by {@jvms 4.7.9}.
*/
public sealed interface MethodSignature
permits SignaturesImpl.MethodSignatureImpl {
/** {@return the type parameters of this method} */
List<Signature.TypeParam> typeParameters();
/** {@return the signatures of the parameters of this method} */
List<Signature> arguments();
/** {@return the signatures of the return value of this method} */
Signature result();
/** {@return the signatures of the exceptions thrown by this method} */
List<Signature.ThrowableSig> throwableSignatures();
/** {@return the raw signature string} */
String signatureString();
/**
* @return method signature for a raw (no generic information) method descriptor
* @param methodDescriptor the method descriptor
*/
public static MethodSignature of(MethodTypeDesc methodDescriptor) {
requireNonNull(methodDescriptor);
return new SignaturesImpl.MethodSignatureImpl(
List.of(),
List.of(),
Signature.of(methodDescriptor.returnType()),
Util.mappedList(methodDescriptor.parameterList(), Signature::of));
}
/**
* @return method signature
* @param result signature for the return type
* @param arguments signatures for the method arguments
*/
public static MethodSignature of(Signature result,
Signature... arguments) {
return new SignaturesImpl.MethodSignatureImpl(List.of(),
List.of(),
requireNonNull(result),
List.of(arguments));
}
/**
* @return method signature
* @param typeParameters signatures for the type parameters
* @param exceptions sigantures for the exceptions
* @param result signature for the return type
* @param arguments signatures for the method arguments
*/
public static MethodSignature of(List<Signature.TypeParam> typeParameters,
List<Signature.ThrowableSig> exceptions,
Signature result,
Signature... arguments) {
return new SignaturesImpl.MethodSignatureImpl(
List.copyOf(requireNonNull(typeParameters)),
List.copyOf(requireNonNull(exceptions)),
requireNonNull(result),
List.of(arguments));
}
/**
* Parses a raw method signature string into a {@linkplain MethodSignature}
* @param methodSignature the raw method signature string
* @return method signature
*/
public static MethodSignature parseFrom(String methodSignature) {
return new SignaturesImpl().parseMethodSignature(requireNonNull(methodSignature));
}
}

View File

@ -0,0 +1,121 @@
/*
* 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 jdk.internal.classfile;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl;
/**
* A transformation on streams of {@link MethodElement}.
*
* @see ClassfileTransform
*/
@FunctionalInterface
public non-sealed interface MethodTransform
extends ClassfileTransform<MethodTransform, MethodElement, MethodBuilder> {
/**
* A method transform that sends all elements to the builder.
*/
MethodTransform ACCEPT_ALL = new MethodTransform() {
@Override
public void accept(MethodBuilder builder, MethodElement element) {
builder.with(element);
}
};
/**
* Create a stateful method transform from a {@link Supplier}. The supplier
* will be invoked for each transformation.
*
* @param supplier a {@link Supplier} that produces a fresh transform object
* for each traversal
* @return the stateful method transform
*/
static MethodTransform ofStateful(Supplier<MethodTransform> supplier) {
return new TransformImpl.SupplierMethodTransform(supplier);
}
/**
* Create a method transform that passes each element through to the builder,
* and calls the specified function when transformation is complete.
*
* @param finisher the function to call when transformation is complete
* @return the method transform
*/
static MethodTransform endHandler(Consumer<MethodBuilder> finisher) {
return new MethodTransform() {
@Override
public void accept(MethodBuilder builder, MethodElement element) {
builder.with(element);
}
@Override
public void atEnd(MethodBuilder builder) {
finisher.accept(builder);
}
};
}
/**
* Create a method transform that passes each element through to the builder,
* except for those that the supplied {@link Predicate} is true for.
*
* @param filter the predicate that determines which elements to drop
* @return the method transform
*/
static MethodTransform dropping(Predicate<MethodElement> filter) {
return (b, e) -> {
if (!filter.test(e))
b.with(e);
};
}
/**
* Create a method transform that transforms {@link CodeModel} elements
* with the supplied code transform.
*
* @param xform the method transform
* @return the class transform
*/
static MethodTransform transformingCode(CodeTransform xform) {
return new TransformImpl.MethodCodeTransform(xform);
}
@Override
default ResolvedTransform<MethodElement> resolve(MethodBuilder builder) {
return new TransformImpl.ResolvedTransformImpl<>(e -> accept(builder, e),
() -> atEnd(builder),
() -> atStart(builder));
}
@Override
default MethodTransform andThen(MethodTransform t) {
return new TransformImpl.ChainedMethodTransform(this, t);
}
}

View File

@ -0,0 +1,338 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ConstantDesc;
import java.lang.constant.ConstantDescs;
/**
* Describes the opcodes of the JVM instruction set, as well as a number of
* pseudo-instructions that may be encountered when traversing the instructions
* of a method.
*
* @see Instruction
* @see PseudoInstruction
*/
public enum Opcode {
NOP(Classfile.NOP, 1, Kind.NOP),
ACONST_NULL(Classfile.ACONST_NULL, 1, Kind.CONSTANT, TypeKind.ReferenceType, 0, ConstantDescs.NULL),
ICONST_M1(Classfile.ICONST_M1, 1, Kind.CONSTANT, TypeKind.IntType, 0, -1),
ICONST_0(Classfile.ICONST_0, 1, Kind.CONSTANT, TypeKind.IntType, 0, 0),
ICONST_1(Classfile.ICONST_1, 1, Kind.CONSTANT, TypeKind.IntType, 0, 1),
ICONST_2(Classfile.ICONST_2, 1, Kind.CONSTANT, TypeKind.IntType, 0, 2),
ICONST_3(Classfile.ICONST_3, 1, Kind.CONSTANT, TypeKind.IntType, 0, 3),
ICONST_4(Classfile.ICONST_4, 1, Kind.CONSTANT, TypeKind.IntType, 0, 4),
ICONST_5(Classfile.ICONST_5, 1, Kind.CONSTANT, TypeKind.IntType, 0, 5),
LCONST_0(Classfile.LCONST_0, 1, Kind.CONSTANT, TypeKind.LongType, 0, 0L),
LCONST_1(Classfile.LCONST_1, 1, Kind.CONSTANT, TypeKind.LongType, 0, 1L),
FCONST_0(Classfile.FCONST_0, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 0.0f),
FCONST_1(Classfile.FCONST_1, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 1.0f),
FCONST_2(Classfile.FCONST_2, 1, Kind.CONSTANT, TypeKind.FloatType, 0, 2.0f),
DCONST_0(Classfile.DCONST_0, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 0.0d),
DCONST_1(Classfile.DCONST_1, 1, Kind.CONSTANT, TypeKind.DoubleType, 0, 1.0d),
BIPUSH(Classfile.BIPUSH, 2, Kind.CONSTANT, TypeKind.ByteType),
SIPUSH(Classfile.SIPUSH, 3, Kind.CONSTANT, TypeKind.ShortType),
LDC(Classfile.LDC, 2, Kind.CONSTANT),
LDC_W(Classfile.LDC_W, 3, Kind.CONSTANT),
LDC2_W(Classfile.LDC2_W, 3, Kind.CONSTANT),
ILOAD(Classfile.ILOAD, 2, Kind.LOAD, TypeKind.IntType, -1),
LLOAD(Classfile.LLOAD, 2, Kind.LOAD, TypeKind.LongType, -1),
FLOAD(Classfile.FLOAD, 2, Kind.LOAD, TypeKind.FloatType, -1),
DLOAD(Classfile.DLOAD, 2, Kind.LOAD, TypeKind.DoubleType, -1),
ALOAD(Classfile.ALOAD, 2, Kind.LOAD, TypeKind.ReferenceType, -1),
ILOAD_0(Classfile.ILOAD_0, 1, Kind.LOAD, TypeKind.IntType, 0),
ILOAD_1(Classfile.ILOAD_1, 1, Kind.LOAD, TypeKind.IntType, 1),
ILOAD_2(Classfile.ILOAD_2, 1, Kind.LOAD, TypeKind.IntType, 2),
ILOAD_3(Classfile.ILOAD_3, 1, Kind.LOAD, TypeKind.IntType, 3),
LLOAD_0(Classfile.LLOAD_0, 1, Kind.LOAD, TypeKind.LongType, 0),
LLOAD_1(Classfile.LLOAD_1, 1, Kind.LOAD, TypeKind.LongType, 1),
LLOAD_2(Classfile.LLOAD_2, 1, Kind.LOAD, TypeKind.LongType, 2),
LLOAD_3(Classfile.LLOAD_3, 1, Kind.LOAD, TypeKind.LongType, 3),
FLOAD_0(Classfile.FLOAD_0, 1, Kind.LOAD, TypeKind.FloatType, 0),
FLOAD_1(Classfile.FLOAD_1, 1, Kind.LOAD, TypeKind.FloatType, 1),
FLOAD_2(Classfile.FLOAD_2, 1, Kind.LOAD, TypeKind.FloatType, 2),
FLOAD_3(Classfile.FLOAD_3, 1, Kind.LOAD, TypeKind.FloatType, 3),
DLOAD_0(Classfile.DLOAD_0, 1, Kind.LOAD, TypeKind.DoubleType, 0),
DLOAD_1(Classfile.DLOAD_1, 1, Kind.LOAD, TypeKind.DoubleType, 1),
DLOAD_2(Classfile.DLOAD_2, 1, Kind.LOAD, TypeKind.DoubleType, 2),
DLOAD_3(Classfile.DLOAD_3, 1, Kind.LOAD, TypeKind.DoubleType, 3),
ALOAD_0(Classfile.ALOAD_0, 1, Kind.LOAD, TypeKind.ReferenceType, 0),
ALOAD_1(Classfile.ALOAD_1, 1, Kind.LOAD, TypeKind.ReferenceType, 1),
ALOAD_2(Classfile.ALOAD_2, 1, Kind.LOAD, TypeKind.ReferenceType, 2),
ALOAD_3(Classfile.ALOAD_3, 1, Kind.LOAD, TypeKind.ReferenceType, 3),
IALOAD(Classfile.IALOAD, 1, Kind.ARRAY_LOAD, TypeKind.IntType),
LALOAD(Classfile.LALOAD, 1, Kind.ARRAY_LOAD, TypeKind.LongType),
FALOAD(Classfile.FALOAD, 1, Kind.ARRAY_LOAD, TypeKind.FloatType),
DALOAD(Classfile.DALOAD, 1, Kind.ARRAY_LOAD, TypeKind.DoubleType),
AALOAD(Classfile.AALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ReferenceType),
BALOAD(Classfile.BALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ByteType),
CALOAD(Classfile.CALOAD, 1, Kind.ARRAY_LOAD, TypeKind.CharType),
SALOAD(Classfile.SALOAD, 1, Kind.ARRAY_LOAD, TypeKind.ShortType),
ISTORE(Classfile.ISTORE, 2, Kind.STORE, TypeKind.IntType, -1),
LSTORE(Classfile.LSTORE, 2, Kind.STORE, TypeKind.LongType, -1),
FSTORE(Classfile.FSTORE, 2, Kind.STORE, TypeKind.FloatType, -1),
DSTORE(Classfile.DSTORE, 2, Kind.STORE, TypeKind.DoubleType, -1),
ASTORE(Classfile.ASTORE, 2, Kind.STORE, TypeKind.ReferenceType, -1),
ISTORE_0(Classfile.ISTORE_0, 1, Kind.STORE, TypeKind.IntType, 0),
ISTORE_1(Classfile.ISTORE_1, 1, Kind.STORE, TypeKind.IntType, 1),
ISTORE_2(Classfile.ISTORE_2, 1, Kind.STORE, TypeKind.IntType, 2),
ISTORE_3(Classfile.ISTORE_3, 1, Kind.STORE, TypeKind.IntType, 3),
LSTORE_0(Classfile.LSTORE_0, 1, Kind.STORE, TypeKind.LongType, 0),
LSTORE_1(Classfile.LSTORE_1, 1, Kind.STORE, TypeKind.LongType, 1),
LSTORE_2(Classfile.LSTORE_2, 1, Kind.STORE, TypeKind.LongType, 2),
LSTORE_3(Classfile.LSTORE_3, 1, Kind.STORE, TypeKind.LongType, 3),
FSTORE_0(Classfile.FSTORE_0, 1, Kind.STORE, TypeKind.FloatType, 0),
FSTORE_1(Classfile.FSTORE_1, 1, Kind.STORE, TypeKind.FloatType, 1),
FSTORE_2(Classfile.FSTORE_2, 1, Kind.STORE, TypeKind.FloatType, 2),
FSTORE_3(Classfile.FSTORE_3, 1, Kind.STORE, TypeKind.FloatType, 3),
DSTORE_0(Classfile.DSTORE_0, 1, Kind.STORE, TypeKind.DoubleType, 0),
DSTORE_1(Classfile.DSTORE_1, 1, Kind.STORE, TypeKind.DoubleType, 1),
DSTORE_2(Classfile.DSTORE_2, 1, Kind.STORE, TypeKind.DoubleType, 2),
DSTORE_3(Classfile.DSTORE_3, 1, Kind.STORE, TypeKind.DoubleType, 3),
ASTORE_0(Classfile.ASTORE_0, 1, Kind.STORE, TypeKind.ReferenceType, 0),
ASTORE_1(Classfile.ASTORE_1, 1, Kind.STORE, TypeKind.ReferenceType, 1),
ASTORE_2(Classfile.ASTORE_2, 1, Kind.STORE, TypeKind.ReferenceType, 2),
ASTORE_3(Classfile.ASTORE_3, 1, Kind.STORE, TypeKind.ReferenceType, 3),
IASTORE(Classfile.IASTORE, 1, Kind.ARRAY_STORE, TypeKind.IntType),
LASTORE(Classfile.LASTORE, 1, Kind.ARRAY_STORE, TypeKind.LongType),
FASTORE(Classfile.FASTORE, 1, Kind.ARRAY_STORE, TypeKind.FloatType),
DASTORE(Classfile.DASTORE, 1, Kind.ARRAY_STORE, TypeKind.DoubleType),
AASTORE(Classfile.AASTORE, 1, Kind.ARRAY_STORE, TypeKind.ReferenceType),
BASTORE(Classfile.BASTORE, 1, Kind.ARRAY_STORE, TypeKind.ByteType),
CASTORE(Classfile.CASTORE, 1, Kind.ARRAY_STORE, TypeKind.CharType),
SASTORE(Classfile.SASTORE, 1, Kind.ARRAY_STORE, TypeKind.ShortType),
POP(Classfile.POP, 1, Kind.STACK),
POP2(Classfile.POP2, 1, Kind.STACK),
DUP(Classfile.DUP, 1, Kind.STACK),
DUP_X1(Classfile.DUP_X1, 1, Kind.STACK),
DUP_X2(Classfile.DUP_X2, 1, Kind.STACK),
DUP2(Classfile.DUP2, 1, Kind.STACK),
DUP2_X1(Classfile.DUP2_X1, 1, Kind.STACK),
DUP2_X2(Classfile.DUP2_X2, 1, Kind.STACK),
SWAP(Classfile.SWAP, 1, Kind.STACK),
IADD(Classfile.IADD, 1, Kind.OPERATOR, TypeKind.IntType),
LADD(Classfile.LADD, 1, Kind.OPERATOR, TypeKind.LongType),
FADD(Classfile.FADD, 1, Kind.OPERATOR, TypeKind.FloatType),
DADD(Classfile.DADD, 1, Kind.OPERATOR, TypeKind.DoubleType),
ISUB(Classfile.ISUB, 1, Kind.OPERATOR, TypeKind.IntType),
LSUB(Classfile.LSUB, 1, Kind.OPERATOR, TypeKind.LongType),
FSUB(Classfile.FSUB, 1, Kind.OPERATOR, TypeKind.FloatType),
DSUB(Classfile.DSUB, 1, Kind.OPERATOR, TypeKind.DoubleType),
IMUL(Classfile.IMUL, 1, Kind.OPERATOR, TypeKind.IntType),
LMUL(Classfile.LMUL, 1, Kind.OPERATOR, TypeKind.LongType),
FMUL(Classfile.FMUL, 1, Kind.OPERATOR, TypeKind.FloatType),
DMUL(Classfile.DMUL, 1, Kind.OPERATOR, TypeKind.DoubleType),
IDIV(Classfile.IDIV, 1, Kind.OPERATOR, TypeKind.IntType),
LDIV(Classfile.LDIV, 1, Kind.OPERATOR, TypeKind.LongType),
FDIV(Classfile.FDIV, 1, Kind.OPERATOR, TypeKind.FloatType),
DDIV(Classfile.DDIV, 1, Kind.OPERATOR, TypeKind.DoubleType),
IREM(Classfile.IREM, 1, Kind.OPERATOR, TypeKind.IntType),
LREM(Classfile.LREM, 1, Kind.OPERATOR, TypeKind.LongType),
FREM(Classfile.FREM, 1, Kind.OPERATOR, TypeKind.FloatType),
DREM(Classfile.DREM, 1, Kind.OPERATOR, TypeKind.DoubleType),
INEG(Classfile.INEG, 1, Kind.OPERATOR, TypeKind.IntType),
LNEG(Classfile.LNEG, 1, Kind.OPERATOR, TypeKind.LongType),
FNEG(Classfile.FNEG, 1, Kind.OPERATOR, TypeKind.FloatType),
DNEG(Classfile.DNEG, 1, Kind.OPERATOR, TypeKind.DoubleType),
ISHL(Classfile.ISHL, 1, Kind.OPERATOR, TypeKind.IntType),
LSHL(Classfile.LSHL, 1, Kind.OPERATOR, TypeKind.LongType),
ISHR(Classfile.ISHR, 1, Kind.OPERATOR, TypeKind.IntType),
LSHR(Classfile.LSHR, 1, Kind.OPERATOR, TypeKind.LongType),
IUSHR(Classfile.IUSHR, 1, Kind.OPERATOR, TypeKind.IntType),
LUSHR(Classfile.LUSHR, 1, Kind.OPERATOR, TypeKind.LongType),
IAND(Classfile.IAND, 1, Kind.OPERATOR, TypeKind.IntType),
LAND(Classfile.LAND, 1, Kind.OPERATOR, TypeKind.LongType),
IOR(Classfile.IOR, 1, Kind.OPERATOR, TypeKind.IntType),
LOR(Classfile.LOR, 1, Kind.OPERATOR, TypeKind.LongType),
IXOR(Classfile.IXOR, 1, Kind.OPERATOR, TypeKind.IntType),
LXOR(Classfile.LXOR, 1, Kind.OPERATOR, TypeKind.LongType),
IINC(Classfile.IINC, 3, Kind.INCREMENT, TypeKind.IntType, -1),
I2L(Classfile.I2L, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.LongType),
I2F(Classfile.I2F, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.FloatType),
I2D(Classfile.I2D, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.DoubleType),
L2I(Classfile.L2I, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.IntType),
L2F(Classfile.L2F, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.FloatType),
L2D(Classfile.L2D, 1, Kind.CONVERT, TypeKind.LongType, TypeKind.DoubleType),
F2I(Classfile.F2I, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.IntType),
F2L(Classfile.F2L, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.LongType),
F2D(Classfile.F2D, 1, Kind.CONVERT, TypeKind.FloatType, TypeKind.DoubleType),
D2I(Classfile.D2I, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.IntType),
D2L(Classfile.D2L, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.LongType),
D2F(Classfile.D2F, 1, Kind.CONVERT, TypeKind.DoubleType, TypeKind.FloatType),
I2B(Classfile.I2B, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ByteType),
I2C(Classfile.I2C, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.CharType),
I2S(Classfile.I2S, 1, Kind.CONVERT, TypeKind.IntType, TypeKind.ShortType),
LCMP(Classfile.LCMP, 1, Kind.OPERATOR, TypeKind.LongType),
FCMPL(Classfile.FCMPL, 1, Kind.OPERATOR, TypeKind.FloatType),
FCMPG(Classfile.FCMPG, 1, Kind.OPERATOR, TypeKind.FloatType),
DCMPL(Classfile.DCMPL, 1, Kind.OPERATOR, TypeKind.DoubleType),
DCMPG(Classfile.DCMPG, 1, Kind.OPERATOR, TypeKind.DoubleType),
IFEQ(Classfile.IFEQ, 3, Kind.BRANCH, TypeKind.IntType),
IFNE(Classfile.IFNE, 3, Kind.BRANCH, TypeKind.IntType),
IFLT(Classfile.IFLT, 3, Kind.BRANCH, TypeKind.IntType),
IFGE(Classfile.IFGE, 3, Kind.BRANCH, TypeKind.IntType),
IFGT(Classfile.IFGT, 3, Kind.BRANCH, TypeKind.IntType),
IFLE(Classfile.IFLE, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPEQ(Classfile.IF_ICMPEQ, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPNE(Classfile.IF_ICMPNE, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPLT(Classfile.IF_ICMPLT, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPGE(Classfile.IF_ICMPGE, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPGT(Classfile.IF_ICMPGT, 3, Kind.BRANCH, TypeKind.IntType),
IF_ICMPLE(Classfile.IF_ICMPLE, 3, Kind.BRANCH, TypeKind.IntType),
IF_ACMPEQ(Classfile.IF_ACMPEQ, 3, Kind.BRANCH, TypeKind.ReferenceType),
IF_ACMPNE(Classfile.IF_ACMPNE, 3, Kind.BRANCH, TypeKind.ReferenceType),
GOTO(Classfile.GOTO, 3, Kind.BRANCH, TypeKind.VoidType),
JSR(Classfile.JSR, 3, Kind.UNSUPPORTED),
RET(Classfile.RET, 2, Kind.UNSUPPORTED),
TABLESWITCH(Classfile.TABLESWITCH, -1, Kind.TABLE_SWITCH),
LOOKUPSWITCH(Classfile.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH),
IRETURN(Classfile.IRETURN, 1, Kind.RETURN, TypeKind.IntType),
LRETURN(Classfile.LRETURN, 1, Kind.RETURN, TypeKind.LongType),
FRETURN(Classfile.FRETURN, 1, Kind.RETURN, TypeKind.FloatType),
DRETURN(Classfile.DRETURN, 1, Kind.RETURN, TypeKind.DoubleType),
ARETURN(Classfile.ARETURN, 1, Kind.RETURN, TypeKind.ReferenceType),
RETURN(Classfile.RETURN, 1, Kind.RETURN, TypeKind.VoidType),
GETSTATIC(Classfile.GETSTATIC, 3, Kind.FIELD_ACCESS),
PUTSTATIC(Classfile.PUTSTATIC, 3, Kind.FIELD_ACCESS),
GETFIELD(Classfile.GETFIELD, 3, Kind.FIELD_ACCESS),
PUTFIELD(Classfile.PUTFIELD, 3, Kind.FIELD_ACCESS),
INVOKEVIRTUAL(Classfile.INVOKEVIRTUAL, 3, Kind.INVOKE),
INVOKESPECIAL(Classfile.INVOKESPECIAL, 3, Kind.INVOKE),
INVOKESTATIC(Classfile.INVOKESTATIC, 3, Kind.INVOKE),
INVOKEINTERFACE(Classfile.INVOKEINTERFACE, 5, Kind.INVOKE),
INVOKEDYNAMIC(Classfile.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC),
NEW(Classfile.NEW, 3, Kind.NEW_OBJECT),
NEWARRAY(Classfile.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY),
ANEWARRAY(Classfile.ANEWARRAY, 3, Kind.NEW_REF_ARRAY),
ARRAYLENGTH(Classfile.ARRAYLENGTH, 1, Kind.OPERATOR, TypeKind.IntType),
ATHROW(Classfile.ATHROW, 1, Kind.THROW_EXCEPTION),
CHECKCAST(Classfile.CHECKCAST, 3, Kind.TYPE_CHECK),
INSTANCEOF(Classfile.INSTANCEOF, 3, Kind.TYPE_CHECK),
MONITORENTER(Classfile.MONITORENTER, 1, Kind.MONITOR),
MONITOREXIT(Classfile.MONITOREXIT, 1, Kind.MONITOR),
MULTIANEWARRAY(Classfile.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY),
IFNULL(Classfile.IFNULL, 3, Kind.BRANCH, TypeKind.ReferenceType),
IFNONNULL(Classfile.IFNONNULL, 3, Kind.BRANCH, TypeKind.IntType),
GOTO_W(Classfile.GOTO_W, 5, Kind.BRANCH, TypeKind.VoidType),
JSR_W(Classfile.JSR_W, 5, Kind.UNSUPPORTED),
ILOAD_W((Classfile.WIDE << 8) | Classfile.ILOAD, 4, Kind.LOAD, TypeKind.IntType, -1),
LLOAD_W((Classfile.WIDE << 8) | Classfile.LLOAD, 4, Kind.LOAD, TypeKind.LongType, -1),
FLOAD_W((Classfile.WIDE << 8) | Classfile.FLOAD, 4, Kind.LOAD, TypeKind.FloatType, -1),
DLOAD_W((Classfile.WIDE << 8) | Classfile.DLOAD, 4, Kind.LOAD, TypeKind.DoubleType, -1),
ALOAD_W((Classfile.WIDE << 8) | Classfile.ALOAD, 4, Kind.LOAD, TypeKind.ReferenceType, -1),
ISTORE_W((Classfile.WIDE << 8) | Classfile.ISTORE, 4, Kind.STORE, TypeKind.IntType, -1),
LSTORE_W((Classfile.WIDE << 8) | Classfile.LSTORE, 4, Kind.STORE, TypeKind.LongType, -1),
FSTORE_W((Classfile.WIDE << 8) | Classfile.FSTORE, 4, Kind.STORE, TypeKind.FloatType, -1),
DSTORE_W((Classfile.WIDE << 8) | Classfile.DSTORE, 4, Kind.STORE, TypeKind.DoubleType, -1),
ASTORE_W((Classfile.WIDE << 8) | Classfile.ASTORE, 4, Kind.STORE, TypeKind.ReferenceType, -1),
RET_W((Classfile.WIDE << 8) | Classfile.RET, 4, Kind.UNSUPPORTED),
IINC_W((Classfile.WIDE << 8) | Classfile.IINC, 6, Kind.INCREMENT, TypeKind.IntType, -1);
/**
* Kinds of opcodes.
*/
public static enum Kind {
LOAD, STORE, INCREMENT, BRANCH, LOOKUP_SWITCH, TABLE_SWITCH, RETURN, THROW_EXCEPTION,
FIELD_ACCESS, INVOKE, INVOKE_DYNAMIC,
NEW_OBJECT, NEW_PRIMITIVE_ARRAY, NEW_REF_ARRAY, NEW_MULTI_ARRAY,
TYPE_CHECK, ARRAY_LOAD, ARRAY_STORE, STACK, CONVERT, OPERATOR, CONSTANT,
MONITOR, NOP, UNSUPPORTED;
}
private final int bytecode;
private final int sizeIfFixed;
private final Kind kind;
private final TypeKind primaryTypeKind;
private final TypeKind secondaryTypeKind;
private final int slot;
private final ConstantDesc constantValue;
Opcode(int bytecode, int sizeIfFixed, Kind kind) {
this(bytecode, sizeIfFixed, kind, null, null, 0, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind) {
this(bytecode, sizeIfFixed, kind, typeKind, null, 0, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot) {
this(bytecode, sizeIfFixed, kind, typeKind, null, slot, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot, ConstantDesc constantValue) {
this(bytecode, sizeIfFixed, kind, typeKind, null, slot, constantValue);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind primaryTypeKind, TypeKind secondaryTypeKind) {
this(bytecode, sizeIfFixed, kind, primaryTypeKind, secondaryTypeKind, 0, null);
}
Opcode(int bytecode,
int sizeIfFixed,
Kind kind,
TypeKind primaryTypeKind,
TypeKind secondaryTypeKind,
int slot,
ConstantDesc constantValue) {
this.bytecode = bytecode;
this.sizeIfFixed = sizeIfFixed;
this.kind = kind;
this.primaryTypeKind = primaryTypeKind;
this.secondaryTypeKind = secondaryTypeKind;
this.slot = slot;
this.constantValue = constantValue;
}
public int bytecode() { return bytecode; }
public boolean isWide() { return bytecode > 255; }
public int sizeIfFixed() { return sizeIfFixed; }
public Kind kind() { return kind; }
public TypeKind primaryTypeKind() {
return primaryTypeKind;
}
public TypeKind secondaryTypeKind() {
return secondaryTypeKind;
}
public int slot() {
return slot;
}
public ConstantDesc constantValue() {
return constantValue;
}
public boolean isUnconditionalBranch() {
return switch (this) {
case GOTO, ATHROW, GOTO_W, LOOKUPSWITCH, TABLESWITCH -> true;
default -> kind() == Kind.RETURN;
};
}
}

View File

@ -0,0 +1,47 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.instruction.CharacterRange;
import jdk.internal.classfile.instruction.ExceptionCatch;
import jdk.internal.classfile.instruction.LabelTarget;
import jdk.internal.classfile.instruction.LineNumber;
import jdk.internal.classfile.instruction.LocalVariable;
import jdk.internal.classfile.instruction.LocalVariableType;
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
/**
* Models metadata about a {@link CodeAttribute}, such as entries in the
* exception table, line number table, local variable table, or the mapping
* between instructions and labels. Pseudo-instructions are delivered as part
* of the element stream of a {@link CodeModel}. Delivery of some
* pseudo-instructions can be disabled by modifying the value of classfile
* options (e.g., {@link Classfile.Option#processDebug(boolean)}).
*/
public sealed interface PseudoInstruction
extends CodeElement
permits CharacterRange, ExceptionCatch, LabelTarget, LineNumber, LocalVariable, LocalVariableType, AbstractPseudoInstruction {
}

View File

@ -0,0 +1,331 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.impl.SignaturesImpl;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import jdk.internal.classfile.impl.Util;
/**
* Models generic Java type signatures, as defined in {@jvms 4.7.9.1}.
*/
public sealed interface Signature {
/** {@return the raw signature string} */
String signatureString();
/**
* Parses generic Java type signature from raw string
* @param javaTypeSignature raw Java type signature string
* @return Java type signature
*/
public static Signature parseFrom(String javaTypeSignature) {
return new SignaturesImpl().parseSignature(requireNonNull(javaTypeSignature));
}
/**
* @param classDesc the symbolic description of the Java type
* @return Java type signature
*/
public static Signature of(ClassDesc classDesc) {
requireNonNull(classDesc);
if (classDesc.isArray())
return ArrayTypeSig.of(of(classDesc.componentType()));
if (classDesc.isPrimitive())
return BaseTypeSig.of(classDesc);
return ClassTypeSig.of(classDesc);
}
/**
* Models the signature of a primitive type or void
*/
public sealed interface BaseTypeSig extends Signature
permits SignaturesImpl.BaseTypeSigImpl {
/** {@return the single-letter descriptor for the base type} */
char baseType();
/**
* {@return the signature of a primitive type or void}
* @param classDesc a symbolic descriptor for the base type, must correspond
* to a primitive type
*/
public static BaseTypeSig of(ClassDesc classDesc) {
requireNonNull(classDesc);
if (!classDesc.isPrimitive())
throw new IllegalArgumentException("primitive class type required");
return new SignaturesImpl.BaseTypeSigImpl(classDesc.descriptorString().charAt(0));
}
/**
* {@return the signature of a primitive type or void}
* @param baseType the single-letter descriptor for the base type
*/
public static BaseTypeSig of(char baseType) {
if ("VIJCSBFDZ".indexOf(baseType) < 0)
throw new IllegalArgumentException("invalid base type signature");
return new SignaturesImpl.BaseTypeSigImpl(baseType);
}
}
/**
* Models the signature of a reference type, which may be a class, interface,
* type variable, or array type.
*/
public sealed interface RefTypeSig
extends Signature
permits ArrayTypeSig, ClassTypeSig, TypeVarSig {
}
/**
* Models the signature of a possibly-parameterized class or interface type.
*/
public sealed interface ClassTypeSig
extends RefTypeSig, ThrowableSig
permits SignaturesImpl.ClassTypeSigImpl {
/** {@return the signature of the outer type, if any} */
Optional<ClassTypeSig> outerType();
/** {@return the class name} */
String className();
/** {@return the class name, as a symbolic descriptor} */
default ClassDesc classDesc() {
return ClassDesc.ofInternalName(className());
}
/** {@return the type arguments of the class} */
List<TypeArg> typeArgs();
/**
* {@return a class type signature}
* @param className the name of the class
* @param typeArgs signatures of the type arguments
*/
public static ClassTypeSig of(ClassDesc className, TypeArg... typeArgs) {
return of(null, className, typeArgs);
}
/**
* {@return a class type signature for an inner class}
* @param outerType signature of the outer type
* @param className the name of the class
* @param typeArgs signatures of the type arguments
*/
public static ClassTypeSig of(ClassTypeSig outerType, ClassDesc className, TypeArg... typeArgs) {
requireNonNull(className);
return of(outerType, Util.toInternalName(className), typeArgs);
}
/**
* {@return a class type signature}
* @param className the name of the class
* @param typeArgs signatures of the type arguments
*/
public static ClassTypeSig of(String className, TypeArg... typeArgs) {
return of(null, className, typeArgs);
}
/**
* {@return a class type signature for an inner class}
* @param outerType signature of the outer type
* @param className the name of the class
* @param typeArgs signatures of the type arguments
*/
public static ClassTypeSig of(ClassTypeSig outerType, String className, TypeArg... typeArgs) {
requireNonNull(className);
return new SignaturesImpl.ClassTypeSigImpl(Optional.ofNullable(outerType), className.replace(".", "/"), List.of(typeArgs));
}
}
/**
* Models the type argument.
*/
public sealed interface TypeArg
permits SignaturesImpl.TypeArgImpl {
/**
* Indicator for whether a wildcard has default bound, no bound,
* an upper bound, or a lower bound
*/
public enum WildcardIndicator {
DEFAULT, UNBOUNDED, EXTENDS, SUPER;
}
/** {@return the wildcard indicator} */
WildcardIndicator wildcardIndicator();
/** {@return the signature of the type bound, if any} */
Optional<RefTypeSig> boundType();
/**
* {@return a bounded type arg}
* @param boundType the bound
*/
public static TypeArg of(RefTypeSig boundType) {
requireNonNull(boundType);
return of(WildcardIndicator.DEFAULT, Optional.of(boundType));
}
/**
* {@return an unbounded type arg}
*/
public static TypeArg unbounded() {
return of(WildcardIndicator.UNBOUNDED, Optional.empty());
}
/**
* {@return an upper-bounded type arg}
* @param boundType the upper bound
*/
public static TypeArg extendsOf(RefTypeSig boundType) {
requireNonNull(boundType);
return of(WildcardIndicator.EXTENDS, Optional.of(boundType));
}
/**
* {@return a lower-bounded type arg}
* @param boundType the lower bound
*/
public static TypeArg superOf(RefTypeSig boundType) {
requireNonNull(boundType);
return of(WildcardIndicator.SUPER, Optional.of(boundType));
}
/**
* {@return a bounded type arg}
* @param wildcard the wild card
* @param boundType optional bound type
*/
public static TypeArg of(WildcardIndicator wildcard, Optional<RefTypeSig> boundType) {
return new SignaturesImpl.TypeArgImpl(wildcard, boundType);
}
}
/**
* Models the signature of a type variable.
*/
public sealed interface TypeVarSig
extends RefTypeSig, ThrowableSig
permits SignaturesImpl.TypeVarSigImpl {
/** {@return the name of the type variable} */
String identifier();
/**
* {@return a signature for a type variable}
* @param identifier the name of the type variable
*/
public static TypeVarSig of(String identifier) {
return new SignaturesImpl.TypeVarSigImpl(requireNonNull(identifier));
}
}
/**
* Models the signature of an array type.
*/
public sealed interface ArrayTypeSig
extends RefTypeSig
permits SignaturesImpl.ArrayTypeSigImpl {
/** {@return the signature of the component type} */
Signature componentSignature();
/**
* {@return a signature for an array type}
* @param componentSignature the component type
*/
public static ArrayTypeSig of(Signature componentSignature) {
return of(1, requireNonNull(componentSignature));
}
/**
* {@return a signature for an array type}
* @param dims the dimension of the array
* @param componentSignature the component type
*/
public static ArrayTypeSig of(int dims, Signature componentSignature) {
requireNonNull(componentSignature);
if (dims < 1 || dims > 255)
throw new IllegalArgumentException("illegal array depth value");
if (componentSignature instanceof SignaturesImpl.ArrayTypeSigImpl arr)
return new SignaturesImpl.ArrayTypeSigImpl(dims + arr.arrayDepth(), arr.elemType());
return new SignaturesImpl.ArrayTypeSigImpl(dims, componentSignature);
}
}
/**
* Models a signature for a type parameter of a generic class or method.
*/
public sealed interface TypeParam
permits SignaturesImpl.TypeParamImpl {
/** {@return the name of the type parameter} */
String identifier();
/** {@return the class bound of the type parameter} */
Optional<RefTypeSig> classBound();
/** {@return the interface bounds of the type parameter} */
List<RefTypeSig> interfaceBounds();
/**
* {@return a signature for a type parameter}
* @param identifier the name of the type parameter
* @param classBound the class bound of the type parameter
* @param interfaceBounds the interface bounds of the type parameter
*/
public static TypeParam of(String identifier, RefTypeSig classBound, RefTypeSig... interfaceBounds) {
return new SignaturesImpl.TypeParamImpl(
requireNonNull(identifier),
Optional.ofNullable(classBound),
List.of(interfaceBounds));
}
/**
* {@return a signature for a type parameter}
* @param identifier the name of the type parameter
* @param classBound the class bound of the type parameter
* @param interfaceBounds the interface bounds of the type parameter
*/
public static TypeParam of(String identifier, Optional<RefTypeSig> classBound, RefTypeSig... interfaceBounds) {
return new SignaturesImpl.TypeParamImpl(
requireNonNull(identifier),
requireNonNull(classBound),
List.of(interfaceBounds));
}
}
/**
* Models a signature for a throwable type.
*/
public sealed interface ThrowableSig extends Signature {
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.SuperclassImpl;
/**
* Models the superclass of a class. Delivered as a {@link
* jdk.internal.classfile.ClassElement} when traversing a {@link ClassModel}.
*/
public sealed interface Superclass
extends ClassElement
permits SuperclassImpl {
/** {@return the superclass} */
ClassEntry superclassEntry();
/**
* {@return a {@linkplain Superclass} element}
* @param superclassEntry the superclass
*/
static Superclass of(ClassEntry superclassEntry) {
return new SuperclassImpl(superclassEntry);
}
}

View File

@ -0,0 +1,642 @@
/*
* 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 jdk.internal.classfile;
import java.lang.constant.ClassDesc;
import java.util.List;
import jdk.internal.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.TargetInfoImpl;
import jdk.internal.classfile.impl.UnboundAttribute;
import static jdk.internal.classfile.Classfile.TAT_CAST;
import static jdk.internal.classfile.Classfile.TAT_CLASS_EXTENDS;
import static jdk.internal.classfile.Classfile.TAT_CLASS_TYPE_PARAMETER;
import static jdk.internal.classfile.Classfile.TAT_CLASS_TYPE_PARAMETER_BOUND;
import static jdk.internal.classfile.Classfile.TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
import static jdk.internal.classfile.Classfile.TAT_CONSTRUCTOR_REFERENCE;
import static jdk.internal.classfile.Classfile.TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
import static jdk.internal.classfile.Classfile.TAT_EXCEPTION_PARAMETER;
import static jdk.internal.classfile.Classfile.TAT_FIELD;
import static jdk.internal.classfile.Classfile.TAT_INSTANCEOF;
import static jdk.internal.classfile.Classfile.TAT_LOCAL_VARIABLE;
import static jdk.internal.classfile.Classfile.TAT_METHOD_FORMAL_PARAMETER;
import static jdk.internal.classfile.Classfile.TAT_METHOD_INVOCATION_TYPE_ARGUMENT;
import static jdk.internal.classfile.Classfile.TAT_METHOD_RECEIVER;
import static jdk.internal.classfile.Classfile.TAT_METHOD_REFERENCE;
import static jdk.internal.classfile.Classfile.TAT_METHOD_REFERENCE_TYPE_ARGUMENT;
import static jdk.internal.classfile.Classfile.TAT_METHOD_RETURN;
import static jdk.internal.classfile.Classfile.TAT_METHOD_TYPE_PARAMETER;
import static jdk.internal.classfile.Classfile.TAT_METHOD_TYPE_PARAMETER_BOUND;
import static jdk.internal.classfile.Classfile.TAT_NEW;
import static jdk.internal.classfile.Classfile.TAT_RESOURCE_VARIABLE;
import static jdk.internal.classfile.Classfile.TAT_THROWS;
import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* Models an annotation on a type use.
*
* @see RuntimeVisibleTypeAnnotationsAttribute
* @see RuntimeInvisibleTypeAnnotationsAttribute
*/
public sealed interface TypeAnnotation
extends Annotation
permits UnboundAttribute.UnboundTypeAnnotation {
/**
* The kind of target on which the annotation appears.
*/
public enum TargetType {
/** For annotations on a class type parameter declaration. */
CLASS_TYPE_PARAMETER(TAT_CLASS_TYPE_PARAMETER, 1),
/** For annotations on a method type parameter declaration. */
METHOD_TYPE_PARAMETER(TAT_METHOD_TYPE_PARAMETER, 1),
/** For annotations on the type of an "extends" or "implements" clause. */
CLASS_EXTENDS(TAT_CLASS_EXTENDS, 2),
/** For annotations on a bound of a type parameter of a class. */
CLASS_TYPE_PARAMETER_BOUND(TAT_CLASS_TYPE_PARAMETER_BOUND, 2),
/** For annotations on a bound of a type parameter of a method. */
METHOD_TYPE_PARAMETER_BOUND(TAT_METHOD_TYPE_PARAMETER_BOUND, 2),
/** For annotations on a field. */
FIELD(TAT_FIELD, 0),
/** For annotations on a method return type. */
METHOD_RETURN(TAT_METHOD_RETURN, 0),
/** For annotations on the method receiver. */
METHOD_RECEIVER(TAT_METHOD_RECEIVER, 0),
/** For annotations on a method parameter. */
METHOD_FORMAL_PARAMETER(TAT_METHOD_FORMAL_PARAMETER, 1),
/** For annotations on a throws clause in a method declaration. */
THROWS(TAT_THROWS, 2),
/** For annotations on a local variable. */
LOCAL_VARIABLE(TAT_LOCAL_VARIABLE, -1),
/** For annotations on a resource variable. */
RESOURCE_VARIABLE(TAT_RESOURCE_VARIABLE, -1),
/** For annotations on an exception parameter. */
EXCEPTION_PARAMETER(TAT_EXCEPTION_PARAMETER, 2),
/** For annotations on a type test. */
INSTANCEOF(TAT_INSTANCEOF, 2),
/** For annotations on an object creation expression. */
NEW(TAT_NEW, 2),
/** For annotations on a constructor reference receiver. */
CONSTRUCTOR_REFERENCE(TAT_CONSTRUCTOR_REFERENCE, 2),
/** For annotations on a method reference receiver. */
METHOD_REFERENCE(TAT_METHOD_REFERENCE, 2),
/** For annotations on a typecast. */
CAST(TAT_CAST, 3),
/** For annotations on a type argument of an object creation expression. */
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a method call. */
METHOD_INVOCATION_TYPE_ARGUMENT(TAT_METHOD_INVOCATION_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a constructor reference. */
CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a method reference. */
METHOD_REFERENCE_TYPE_ARGUMENT(TAT_METHOD_REFERENCE_TYPE_ARGUMENT, 3);
private final int targetTypeValue;
private final int sizeIfFixed;
private TargetType(int targetTypeValue, int sizeIfFixed) {
this.targetTypeValue = targetTypeValue;
this.sizeIfFixed = sizeIfFixed;
}
public int targetTypeValue() {
return targetTypeValue;
}
public int sizeIfFixed() {
return sizeIfFixed;
}
}
/**
* {@return information describing precisely which type in a declaration or expression
* is annotated}
*/
TargetInfo targetInfo();
/**
* {@return which part of the type indicated by {@link #targetInfo()} is annotated}
*/
List<TypePathComponent> targetPath();
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClassUtf8Entry the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry annotationClassUtf8Entry,
List<AnnotationElement> annotationElements) {
return new UnboundAttribute.UnboundTypeAnnotation(targetInfo, targetPath,
annotationClassUtf8Entry, annotationElements);
}
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClass the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
ClassDesc annotationClass,
AnnotationElement... annotationElements) {
return of(targetInfo, targetPath, annotationClass, List.of(annotationElements));
}
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClass the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
ClassDesc annotationClass,
List<AnnotationElement> annotationElements) {
return of(targetInfo, targetPath,
TemporaryConstantPool.INSTANCE.utf8Entry(annotationClass.descriptorString()), annotationElements);
}
/**
* {@return a type annotation}
* @param targetInfo which type in a declaration or expression is annotated
* @param targetPath which part of the type is annotated
* @param annotationClassUtf8Entry the annotation class
* @param annotationElements the annotation elements
*/
static TypeAnnotation of(TargetInfo targetInfo, List<TypePathComponent> targetPath,
Utf8Entry annotationClassUtf8Entry,
AnnotationElement... annotationElements) {
return of(targetInfo, targetPath, annotationClassUtf8Entry, List.of(annotationElements));
}
/**
* Specifies which type in a declaration or expression is being annotated.
*/
sealed interface TargetInfo {
TargetType targetType();
default int size() {
return targetType().sizeIfFixed;
}
static TypeParameterTarget ofTypeParameter(TargetType targetType, int typeParameterIndex) {
return new TargetInfoImpl.TypeParameterTargetImpl(targetType, typeParameterIndex);
}
static TypeParameterTarget ofClassTypeParameter(int typeParameterIndex) {
return ofTypeParameter(TargetType.CLASS_TYPE_PARAMETER, typeParameterIndex);
}
static TypeParameterTarget ofMethodTypeParameter(int typeParameterIndex) {
return ofTypeParameter(TargetType.METHOD_TYPE_PARAMETER, typeParameterIndex);
}
static SupertypeTarget ofClassExtends(int supertypeIndex) {
return new TargetInfoImpl.SupertypeTargetImpl(supertypeIndex);
}
static TypeParameterBoundTarget ofTypeParameterBound(TargetType targetType, int typeParameterIndex, int boundIndex) {
return new TargetInfoImpl.TypeParameterBoundTargetImpl(targetType, typeParameterIndex, boundIndex);
}
static TypeParameterBoundTarget ofClassTypeParameterBound(int typeParameterIndex, int boundIndex) {
return ofTypeParameterBound(TargetType.CLASS_TYPE_PARAMETER_BOUND, typeParameterIndex, boundIndex);
}
static TypeParameterBoundTarget ofMethodTypeParameterBound(int typeParameterIndex, int boundIndex) {
return ofTypeParameterBound(TargetType.METHOD_TYPE_PARAMETER_BOUND, typeParameterIndex, boundIndex);
}
static EmptyTarget of(TargetType targetType) {
return new TargetInfoImpl.EmptyTargetImpl(targetType);
}
static EmptyTarget ofField() {
return of(TargetType.FIELD);
}
static EmptyTarget ofMethodReturn() {
return of(TargetType.METHOD_RETURN);
}
static EmptyTarget ofMethodReceiver() {
return of(TargetType.METHOD_RECEIVER);
}
static FormalParameterTarget ofMethodFormalParameter(int formalParameterIndex) {
return new TargetInfoImpl.FormalParameterTargetImpl(formalParameterIndex);
}
static ThrowsTarget ofThrows(int throwsTargetIndex) {
return new TargetInfoImpl.ThrowsTargetImpl(throwsTargetIndex);
}
static LocalVarTarget ofVariable(TargetType targetType, List<LocalVarTargetInfo> table) {
return new TargetInfoImpl.LocalVarTargetImpl(targetType, table);
}
static LocalVarTarget ofLocalVariable(List<LocalVarTargetInfo> table) {
return ofVariable(TargetType.LOCAL_VARIABLE, table);
}
static LocalVarTarget ofResourceVariable(List<LocalVarTargetInfo> table) {
return ofVariable(TargetType.RESOURCE_VARIABLE, table);
}
static CatchTarget ofExceptionParameter(int exceptionTableIndex) {
return new TargetInfoImpl.CatchTargetImpl(exceptionTableIndex);
}
static OffsetTarget ofOffset(TargetType targetType, Label target) {
return new TargetInfoImpl.OffsetTargetImpl(targetType, target);
}
static OffsetTarget ofInstanceofExpr(Label target) {
return ofOffset(TargetType.INSTANCEOF, target);
}
static OffsetTarget ofNewExpr(Label target) {
return ofOffset(TargetType.NEW, target);
}
static OffsetTarget ofConstructorReference(Label target) {
return ofOffset(TargetType.CONSTRUCTOR_REFERENCE, target);
}
static OffsetTarget ofMethodReference(Label target) {
return ofOffset(TargetType.METHOD_REFERENCE, target);
}
static TypeArgumentTarget ofTypeArgument(TargetType targetType, Label target, int typeArgumentIndex) {
return new TargetInfoImpl.TypeArgumentTargetImpl(targetType, target, typeArgumentIndex);
}
static TypeArgumentTarget ofCastExpr(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CAST, target, typeArgumentIndex);
}
static TypeArgumentTarget ofConstructorInvocationTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, target, typeArgumentIndex);
}
static TypeArgumentTarget ofMethodInvocationTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.METHOD_INVOCATION_TYPE_ARGUMENT, target, typeArgumentIndex);
}
static TypeArgumentTarget ofConstructorReferenceTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT, target, typeArgumentIndex);
}
static TypeArgumentTarget ofMethodReferenceTypeArgument(Label target, int typeArgumentIndex) {
return ofTypeArgument(TargetType.METHOD_REFERENCE_TYPE_ARGUMENT, target, typeArgumentIndex);
}
}
/**
* Indicates that an annotation appears on the declaration of the i'th type
* parameter of a generic class, generic interface, generic method, or
* generic constructor.
*/
sealed interface TypeParameterTarget extends TargetInfo
permits TargetInfoImpl.TypeParameterTargetImpl {
/**
* JVMS: The value of the type_parameter_index item specifies which type parameter declaration is annotated.
* A type_parameter_index value of 0 specifies the first type parameter declaration.
*
* @return the index into the type parameters
*/
int typeParameterIndex();
}
/**
* Indicates that an annotation appears on a type in the extends or implements
* clause of a class or interface declaration.
*/
sealed interface SupertypeTarget extends TargetInfo
permits TargetInfoImpl.SupertypeTargetImpl {
/**
* JVMS: A supertype_index value of 65535 specifies that the annotation appears on the superclass in an extends
* clause of a class declaration.
*
* Any other supertype_index value is an index into the interfaces array of the enclosing ClassFile structure,
* and specifies that the annotation appears on that superinterface in either the implements clause of a class
* declaration or the extends clause of an interface declaration.
*
* @return the index into the interfaces array or 65535 to indicate it is the superclass
*/
int supertypeIndex();
}
/**
* Indicates that an annotation appears on the i'th bound of the j'th
* type parameter declaration of a generic class, interface, method, or
* constructor.
*/
sealed interface TypeParameterBoundTarget extends TargetInfo
permits TargetInfoImpl.TypeParameterBoundTargetImpl {
/**
* Which type parameter declaration has an annotated bound.
*
* @return the zero-origin index into the type parameters
*/
int typeParameterIndex();
/**
* Which bound of the type parameter declaration is annotated.
*
* @return the zero-origin index into bounds on the type parameter
*/
int boundIndex();
}
/**
* Indicates that an annotation appears on either the type in a field
* declaration, the return type of a method, the type of a newly constructed
* object, or the receiver type of a method or constructor.
*/
sealed interface EmptyTarget extends TargetInfo
permits TargetInfoImpl.EmptyTargetImpl {
}
/**
* Indicates that an annotation appears on the type in a formal parameter
* declaration of a method, constructor, or lambda expression.
*/
sealed interface FormalParameterTarget extends TargetInfo
permits TargetInfoImpl.FormalParameterTargetImpl {
/**
* Which formal parameter declaration has an annotated type.
*
* @return the index into the formal parameter declarations, in the order
* declared in the source code
*/
int formalParameterIndex();
}
/**
* Indicates that an annotation appears on the i'th type in the throws
* clause of a method or constructor declaration.
*/
sealed interface ThrowsTarget extends TargetInfo
permits TargetInfoImpl.ThrowsTargetImpl {
/**
* The index into the exception_index_table array of the
* Exceptions attribute of the method_info structure enclosing the
* RuntimeVisibleTypeAnnotations attribute.
*
* @return index into the list jdk.internal.classfile.attribute.ExceptionsAttribute.exceptions()
*/
int throwsTargetIndex();
}
/**
* Indicates that an annotation appears on the type in a local variable declaration,
* including a variable declared as a resource in a try-with-resources statement.
*/
sealed interface LocalVarTarget extends TargetInfo
permits TargetInfoImpl.LocalVarTargetImpl {
/**
* @return the table of local variable location/indicies.
*/
List<LocalVarTargetInfo> table();
}
/**
* Indicates a range of code array offsets within which a local variable
* has a value, and the index into the local variable array of the current
* frame at which that local variable can be found.
*/
sealed interface LocalVarTargetInfo
permits TargetInfoImpl.LocalVarTargetInfoImpl {
/**
* The given local variable has a value at indices into the code array in the interval
* [start_pc, start_pc + length), that is, between start_pc inclusive and start_pc + length exclusive.
*
* @return the start of the bytecode section.
*/
Label startLabel();
/**
* The given local variable has a value at indices into the code array in the interval
* [start_pc, start_pc + length), that is, between start_pc inclusive and start_pc + length exclusive.
*
* @return
*/
Label endLabel();
/**
* The given local variable must be at index in the local variable array of the current frame.
*
* If the local variable at index is of type double or long, it occupies both index and index + 1.
*
* @return index into the local variables
*/
int index();
static LocalVarTargetInfo of(Label startLabel, Label endLabel, int index) {
return new TargetInfoImpl.LocalVarTargetInfoImpl(startLabel, endLabel, index);
}
}
/**
* Indicates that an annotation appears on the i'th type in an exception parameter
* declaration.
*/
sealed interface CatchTarget extends TargetInfo
permits TargetInfoImpl.CatchTargetImpl {
/**
* The index into the exception_table array of the Code
* attribute enclosing the RuntimeVisibleTypeAnnotations attribute.
*
* @return the index into the exception table
*/
int exceptionTableIndex();
}
/**
* Indicates that an annotation appears on either the type in an instanceof expression
* or a new expression, or the type before the :: in a method reference expression.
*/
sealed interface OffsetTarget extends TargetInfo
permits TargetInfoImpl.OffsetTargetImpl {
/**
* The code array offset of either the bytecode instruction
* corresponding to the instanceof expression, the new bytecode instruction corresponding to the new
* expression, or the bytecode instruction corresponding to the method reference expression.
*
* @return
*/
Label target();
}
/**
* Indicates that an annotation appears either on the i'th type in a cast
* expression, or on the i'th type argument in the explicit type argument list for any of the following: a new
* expression, an explicit constructor invocation statement, a method invocation expression, or a method reference
* expression.
*/
sealed interface TypeArgumentTarget extends TargetInfo
permits TargetInfoImpl.TypeArgumentTargetImpl {
/**
* The code array offset of either the bytecode instruction
* corresponding to the cast expression, the new bytecode instruction corresponding to the new expression, the
* bytecode instruction corresponding to the explicit constructor invocation statement, the bytecode
* instruction corresponding to the method invocation expression, or the bytecode instruction corresponding to
* the method reference expression.
*
* @return
*/
Label target();
/**
* For a cast expression, the value of the type_argument_index item specifies which type in the cast
* operator is annotated. A type_argument_index value of 0 specifies the first (or only) type in the cast
* operator.
*
* The possibility of more than one type in a cast expression arises from a cast to an intersection type.
*
* For an explicit type argument list, the value of the type_argument_index item specifies which type argument
* is annotated. A type_argument_index value of 0 specifies the first type argument.
*
* @return the index into the type arguments
*/
int typeArgumentIndex();
}
/**
* JVMS: Wherever a type is used in a declaration or expression, the type_path structure identifies which part of
* the type is annotated. An annotation may appear on the type itself, but if the type is a reference type, then
* there are additional locations where an annotation may appear:
*
* If an array type T[] is used in a declaration or expression, then an annotation may appear on any component type
* of the array type, including the element type.
*
* If a nested type T1.T2 is used in a declaration or expression, then an annotation may appear on the name of the
* innermost member type and any enclosing type for which a type annotation is admissible {@jls 9.7.4}.
*
* If a parameterized type {@literal T<A> or T<? extends A> or T<? super A>} is used in a declaration or expression, then an
* annotation may appear on any type argument or on the bound of any wildcard type argument.
*
* JVMS: ... each entry in the path array represents an iterative, left-to-right step towards the precise location
* of the annotation in an array type, nested type, or parameterized type. (In an array type, the iteration visits
* the array type itself, then its component type, then the component type of that component type, and so on,
* until the element type is reached.)
*/
sealed interface TypePathComponent
permits UnboundAttribute.TypePathComponentImpl {
public enum Kind {
ARRAY(0),
INNER_TYPE(1),
WILDCARD(2),
TYPE_ARGUMENT(3);
private final int tag;
private Kind(int tag) {
this.tag = tag;
}
public int tag() {
return tag;
}
}
TypePathComponent ARRAY = new UnboundAttribute.TypePathComponentImpl(Kind.ARRAY, 0);
TypePathComponent INNER_TYPE = new UnboundAttribute.TypePathComponentImpl(Kind.INNER_TYPE, 0);
TypePathComponent WILDCARD = new UnboundAttribute.TypePathComponentImpl(Kind.WILDCARD, 0);
/**
* The type path kind items from JVMS Table 4.7.20.2-A.
*
* @return the kind of path element
*/
Kind typePathKind();
/**
* JVMS: type_argument_index
* If the value of the type_path_kind item is 0, 1, or 2, then the value of the type_argument_index item is 0.
*
* If the value of the type_path_kind item is 3, then the value of the type_argument_index item specifies which
* type argument of a parameterized type is annotated, where 0 indicates the first type argument of a
* parameterized type.
*
* @return the index within the type component
*/
int typeArgumentIndex();
static TypePathComponent of(Kind typePathKind, int typeArgumentIndex) {
return switch (typePathKind) {
case ARRAY -> ARRAY;
case INNER_TYPE -> INNER_TYPE;
case WILDCARD -> WILDCARD;
case TYPE_ARGUMENT -> new UnboundAttribute.TypePathComponentImpl(Kind.TYPE_ARGUMENT, typeArgumentIndex);
};
}
}
}

View File

@ -0,0 +1,133 @@
/*
* 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 jdk.internal.classfile;
/**
* Describes the types that can be part of a field or method descriptor.
*/
public enum TypeKind {
/** the primitive type byte */
ByteType("byte", "B", 8),
/** the primitive type short */
ShortType("short", "S", 9),
/** the primitive type int */
IntType("int", "I", 10),
/** the primitive type float */
FloatType("float", "F", 6),
/** the primitive type long */
LongType("long", "J", 11),
/** the primitive type double */
DoubleType("double", "D", 7),
/** a reference type */
ReferenceType("reference type", "L", -1),
/** the primitive type char */
CharType("char", "C", 5),
/** the primitive type boolean */
BooleanType("boolean", "Z", 4),
/** void */
VoidType("void", "V", -1);
private static TypeKind[] newarraycodeToTypeTag;
private final String name;
private final String descriptor;
private final int newarraycode;
/** {@return the human-readable name corresponding to this type} */
public String typeName() { return name; }
/** {@return the field descriptor character corresponding to this type} */
public String descriptor() { return descriptor; }
/** {@return the code used by the {@code newarray} opcode corresponding to this type} */
public int newarraycode() {
return newarraycode;
}
/**
* {@return the number of local variable slots consumed by this type}
*/
public int slotSize() {
return switch (this) {
case VoidType -> 0;
case LongType, DoubleType -> 2;
default -> 1;
};
}
/**
* Erase this type kind to the type which will be used for xLOAD, xSTORE,
* and xRETURN bytecodes
* @return the erased type kind
*/
public TypeKind asLoadable() {
return switch (this) {
case BooleanType, ByteType, CharType, ShortType -> TypeKind.IntType;
default -> this;
};
}
TypeKind(String name, String descriptor, int newarraycode) {
this.name = name;
this.descriptor = descriptor;
this.newarraycode = newarraycode;
}
/**
* {@return the type kind associated with the array type described by the
* array code used as an operand to {@code newarray}}
* @param newarraycode the operand of the {@code newarray} instruction
*/
public static TypeKind fromNewArrayCode(int newarraycode) {
if (newarraycodeToTypeTag == null) {
newarraycodeToTypeTag = new TypeKind[12];
for (TypeKind tag : TypeKind.values()) {
if (tag.newarraycode > 0) newarraycodeToTypeTag[tag.newarraycode] = tag;
}
}
return newarraycodeToTypeTag[newarraycode];
}
/**
* {@return the type kind associated with the specified field descriptor}
* @param s the field descriptor
*/
public static TypeKind fromDescriptor(CharSequence s) {
return switch (s.charAt(0)) {
case '[', 'L' -> TypeKind.ReferenceType;
case 'B' -> TypeKind.ByteType;
case 'C' -> TypeKind.CharType;
case 'Z' -> TypeKind.BooleanType;
case 'S' -> TypeKind.ShortType;
case 'I' -> TypeKind.IntType;
case 'F' -> TypeKind.FloatType;
case 'J' -> TypeKind.LongType;
case 'D' -> TypeKind.DoubleType;
case 'V' -> TypeKind.VoidType;
default -> throw new IllegalStateException("Bad type: " + s);
};
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 jdk.internal.classfile;
import jdk.internal.classfile.constantpool.ConstantPoolBuilder;
import jdk.internal.classfile.constantpool.PoolEntry;
import jdk.internal.classfile.impl.DirectFieldBuilder;
import jdk.internal.classfile.impl.DirectMethodBuilder;
/**
* 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
*/
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

@ -0,0 +1,60 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.AnnotationValue;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.MethodModel;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code AnnotationDefault} attribute {@jvms 4.7.22}, which can
* appear on methods of annotation types, and records the default value
* {@jls 9.6.2} for the element corresponding to this method. Delivered as a
* {@link MethodElement} when traversing the elements of a {@link MethodModel}.
*/
public sealed interface AnnotationDefaultAttribute
extends Attribute<AnnotationDefaultAttribute>, MethodElement
permits BoundAttribute.BoundAnnotationDefaultAttr,
UnboundAttribute.UnboundAnnotationDefaultAttribute {
/**
* {@return the default value of the annotation type element represented by
* this method}
*/
AnnotationValue defaultValue();
/**
* {@return an {@code AnnotationDefault} attribute}
* @param annotationDefault the default value of the annotation type element
*/
static AnnotationDefaultAttribute of(AnnotationValue annotationDefault) {
return new UnboundAttribute.UnboundAnnotationDefaultAttribute(annotationDefault);
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.BootstrapMethodEntry;
import jdk.internal.classfile.constantpool.ConstantPool;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code BootstrapMethods} attribute {@jvms 4.7.23}, which serves as
* an extension to the constant pool of a classfile. Elements of the bootstrap
* method table are accessed through {@link ConstantPool}.
*/
public sealed interface BootstrapMethodsAttribute
extends Attribute<BootstrapMethodsAttribute>
permits BoundAttribute.BoundBootstrapMethodsAttribute,
UnboundAttribute.EmptyBootstrapAttribute {
/**
* {@return the elements of the bootstrap method table}
*/
List<BootstrapMethodEntry> bootstrapMethods();
/**
* {@return the size of the bootstrap methods table}. Calling this method
* does not necessarily inflate the entire table.
*/
int bootstrapMethodsSize();
// No factories; BMA is generated as part of constant pool
}

View File

@ -0,0 +1,155 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single character range in the {@link CharacterRangeTableAttribute}.
*/
public sealed interface CharacterRangeInfo
permits UnboundAttribute.UnboundCharacterRangeInfo {
/**
* {@return the start of the character range region (inclusive)} This is
* the index into the code array at which the code for this character range
* begins.
*/
int startPc();
/**
* {@return the end of the character range region (exclusive)} This is the
* index into the code array after which the code for this character range
* ends.
*/
int endPc();
/**
* {@return the encoded start of the character range region (inclusive)}
* The value is constructed from the line_number/column_number pair as given
* by {@code line_number << 10 + column_number}, where the source file is
* viewed as an array of (possibly multi-byte) characters.
*/
int characterRangeStart();
/**
* {@return the encoded end of the character range region (exclusive)}.
* The value is constructed from the line_number/column_number pair as given
* by {@code line_number << 10 + column_number}, where the source file is
* viewed as an array of (possibly multi-byte) characters.
*/
int characterRangeEnd();
/**
* The value of the flags item describes the kind of range. Multiple flags
* may be set within flags.
* <ul>
* <li>{@link jdk.internal.classfile.Classfile#CRT_STATEMENT} Range is a Statement
* (except ExpressionStatement), StatementExpression {@jls 14.8}, as well as each
* VariableDeclaratorId = VariableInitializer of
* LocalVariableDeclarationStatement {@jls 14.4} or FieldDeclaration {@jls 8.3} in the
* grammar.
* <li>{@link jdk.internal.classfile.Classfile#CRT_BLOCK} Range is a Block in the
* grammar.
* <li>{@link jdk.internal.classfile.Classfile#CRT_ASSIGNMENT} Range is an assignment
* expression - Expression1 AssignmentOperator Expression1 in the grammar as
* well as increment and decrement expressions (both prefix and postfix).
* <li>{@link jdk.internal.classfile.Classfile#CRT_FLOW_CONTROLLER} An expression
* whose value will effect control flow. {@code Flowcon} in the following:
* <pre>
* if ( Flowcon ) Statement [else Statement]
* for ( ForInitOpt ; [Flowcon] ; ForUpdateOpt ) Statement
* while ( Flowcon ) Statement
* do Statement while ( Flowcon ) ;
* switch ( Flowcon ) { SwitchBlockStatementGroups }
* Flowcon || Expression3
* Flowcon &amp;&amp; Expression3
* Flowcon ? Expression : Expression1
* </pre>
* <li>{@link jdk.internal.classfile.Classfile#CRT_FLOW_TARGET} Statement or
* expression effected by a CRT_FLOW_CONTROLLER. {@code Flowtarg} in the following:
* <pre>
* if ( Flowcon ) Flowtarg [else Flowtarg]
* for ( ForInitOpt ; [Flowcon] ; ForUpdateOpt ) Flowtarg
* while ( Flowcon ) Flowtarg
* do Flowtarg while ( Flowcon ) ;
* Flowcon || Flowtarg
* Flowcon &amp;&amp; Flowtarg
* Flowcon ? Flowtarg : Flowtarg
* </pre>
* <li>{@link jdk.internal.classfile.Classfile#CRT_INVOKE} Method invocation. For
* example: Identifier Arguments.
* <li>{@link jdk.internal.classfile.Classfile#CRT_CREATE} New object creation. For
* example: new Creator.
* <li>{@link jdk.internal.classfile.Classfile#CRT_BRANCH_TRUE} A condition encoded
* in the branch instruction immediately contained in the code range for
* this item is not inverted towards the corresponding branch condition in
* the source code. I.e. actual jump occurs if and only if the the source
* code branch condition evaluates to true. Entries of this type are
* produced only for conditions that are listed in the description of
* CRT_FLOW_CONTROLLER flag. The source range for the entry contains flow
* controlling expression. start_pc field for an entry of this type must
* point to a branch instruction: if_acmp&lt;cond&gt;, if_icmp&lt;cond&gt;,
* if&lt;cond&gt;, ifnonull, ifnull or goto. CRT_BRANCH_TRUE and
* CRT_BRANCH_FALSE are special kinds of entries that can be used to
* determine what branch of a condition was chosen during the runtime.
* <li>{@link jdk.internal.classfile.Classfile#CRT_BRANCH_FALSE} A condition encoded
* in the branch instruction immediately contained in the code range for
* this item is inverted towards the corresponding branch condition in the
* source code. I.e. actual jump occurs if and only if the the source code
* branch condition evaluates to false. Entries of this type are produced
* only for conditions that are listed in the description of
* CRT_FLOW_CONTROLLER flag. The source range for the entry contains flow
* controlling expression. start_pc field for an entry of this type must
* point to a branch instruction: if_acmp&lt;cond&gt;, if_icmp&lt;cond&gt;,
* if&lt;cond&gt;, ifnonull, ifnull or goto.
* </ul>
* <p>
* All bits of the flags item not assigned above are reserved for future use. They should be set to zero in generated class files and should be ignored by Java virtual machine implementations.
*
* @return the flags
*/
int flags();
/**
* {@return a character range description}
* @param startPc the start of the bytecode range, inclusive
* @param endPc the end of the bytecode range, exclusive
* @param characterRangeStart the start of the character range, inclusive,
* encoded as {@code line_number << 10 + column_number}
* @param characterRangeEnd the end of the character range, exclusive,
* encoded as {@code line_number << 10 + column_number}
* @param flags the range flags
*/
static CharacterRangeInfo of(int startPc,
int endPc,
int characterRangeStart,
int characterRangeEnd,
int flags) {
return new UnboundAttribute.UnboundCharacterRangeInfo(startPc, endPc,
characterRangeStart, characterRangeEnd,
flags);
}
}

View File

@ -0,0 +1,76 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* The CharacterRangeTable attribute is an optional variable-length attribute in
* the attributes table of a {@code Code} attribute. It may be used by debuggers
* to determine which part of the Java virtual machine code array corresponds to
* a given position in the source file or to determine what section of source
* code corresponds to a given index into the code array. The
* CharacterRangeTable attribute consists of an array of character range entries.
* Each character range entry within the table associates a range of indices in
* the code array with a range of character indices in the source file. If the
* source file is viewed as an array of characters, a character index is the
* corresponding index into this array. Note that character indices are not the
* same as byte indices as multi-byte characters may be present in the source
* file. Each character range entry includes a flag which indicates what kind of
* range is described: statement, assignment, method call, etc. Both code index
* ranges and character ranges may nest within other ranges, but they may not
* partially overlap. Thus, a given code index may correspond to several
* character range entries and in turn several character ranges, but there will
* be a smallest character range, and for each kind of range in which it is
* enclosed there will be a smallest character range. Similarly, a given
* character index may correspond to several character range entries and in turn
* several code index ranges, but there will be a smallest code index range, and
* for each kind of range in which it is enclosed there will be a smallest code
* index range. The character range entries may appear in any order.
*/
public sealed interface CharacterRangeTableAttribute
extends Attribute<CharacterRangeTableAttribute>
permits BoundAttribute.BoundCharacterRangeTableAttribute,
UnboundAttribute.UnboundCharacterRangeTableAttribute {
/**
* {@return the entries of the character range table}
*/
List<CharacterRangeInfo> characterRangeTable();
/**
* {@return a {@code CharacterRangeTable} attribute}
* @param ranges the descriptions of the character ranges
*/
static CharacterRangeTableAttribute of(List<CharacterRangeInfo> ranges) {
return new UnboundAttribute.UnboundCharacterRangeTableAttribute(ranges);
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.CodeModel;
import jdk.internal.classfile.Label;
import jdk.internal.classfile.impl.BoundAttribute;
/**
* Models the {@code Code} attribute {@jvms 4.7.3}, appears on non-native,
* non-abstract methods and contains the bytecode of the method body. Delivered
* as a {@link jdk.internal.classfile.MethodElement} when traversing the elements of a
* {@link jdk.internal.classfile.MethodModel}.
*/
public sealed interface CodeAttribute extends Attribute<CodeAttribute>, CodeModel
permits BoundAttribute.BoundCodeAttribute {
/**
* {@return The length of the code array in bytes}
*/
int codeLength();
/**
* {@return the bytes (bytecode) of the code array}
*/
byte[] codeArray();
/**
* {@return the position of the {@code Label} in the {@code codeArray}
* or -1 if the {@code Label} does not point to the {@code codeArray}}
* @param label a marker for a position within this {@code CodeAttribute}
*/
int labelToBci(Label label);
}

View File

@ -0,0 +1,67 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code CompilationID} attribute (@@@ need reference), which can
* appear on classes and records the compilation time of the class. Delivered
* as a {@link jdk.internal.classfile.ClassElement} when traversing the elements of
* a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface CompilationIDAttribute
extends Attribute<CompilationIDAttribute>, ClassElement
permits BoundAttribute.BoundCompilationIDAttribute,
UnboundAttribute.UnboundCompilationIDAttribute {
/**
* {@return the compilation ID} The compilation ID is the value of
* {@link System#currentTimeMillis()} when the classfile is generated.
*/
Utf8Entry compilationId();
/**
* {@return a {@code CompilationID} attribute}
* @param id the compilation ID
*/
static CompilationIDAttribute of(Utf8Entry id) {
return new UnboundAttribute.UnboundCompilationIDAttribute(id);
}
/**
* {@return a {@code CompilationID} attribute}
* @param id the compilation ID
*/
static CompilationIDAttribute of(String id) {
return new UnboundAttribute.UnboundCompilationIDAttribute(TemporaryConstantPool.INSTANCE.utf8Entry(id));
}
}

View File

@ -0,0 +1,73 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ConstantDesc;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.constantpool.ConstantValueEntry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ConstantValue} attribute {@jvms 4.7.2}, which can appear on
* fields and indicates that the field's value is a constant. Delivered as a
* {@link jdk.internal.classfile.FieldElement} when traversing the elements of a
* {@link jdk.internal.classfile.FieldModel}.
*/
public sealed interface ConstantValueAttribute
extends Attribute<ConstantValueAttribute>, FieldElement
permits BoundAttribute.BoundConstantValueAttribute,
UnboundAttribute.UnboundConstantValueAttribute {
/**
* {@return the constant value of the field}
*/
ConstantValueEntry constant();
/**
* {@return a {@code ConstantValue} attribute}
* @param value the constant value
*/
static ConstantValueAttribute of(ConstantValueEntry value) {
return new UnboundAttribute.UnboundConstantValueAttribute(value);
}
/**
* {@return a {@code ConstantValue} attribute}
* @param value the constant value
*/
static ConstantValueAttribute of(ConstantDesc value) {
return of(switch(value) {
case Integer i -> TemporaryConstantPool.INSTANCE.intEntry(i);
case Float f -> TemporaryConstantPool.INSTANCE.floatEntry(f);
case Long l -> TemporaryConstantPool.INSTANCE.longEntry(l);
case Double d -> TemporaryConstantPool.INSTANCE.doubleEntry(d);
case String s -> TemporaryConstantPool.INSTANCE.stringEntry(s);
default -> throw new IllegalArgumentException("Invalid ConstantValueAtrtibute value: " + value);
});
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code Deprecated} attribute {@jvms 4.7.15}, which can appear on
* classes, methods, and fields. Delivered as a {@link ClassElement},
* {@link MethodElement}, or {@link FieldElement} when traversing the elements
* of a corresponding model.
*/
public sealed interface DeprecatedAttribute
extends Attribute<DeprecatedAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundDeprecatedAttribute,
UnboundAttribute.UnboundDeprecatedAttribute {
/**
* {@return a {@code Deprecated} attribute}
*/
static DeprecatedAttribute of() {
return new UnboundAttribute.UnboundDeprecatedAttribute();
}
}

View File

@ -0,0 +1,112 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.util.Optional;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.NameAndTypeEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code EnclosingMethod} attribute {@jvms 4.7.7}, which can appear
* on classes, and indicates that the class is a local or anonymous class.
* Delivered as a {@link ClassElement} when traversing the elements of a {@link
* jdk.internal.classfile.ClassModel}.
*/
public sealed interface EnclosingMethodAttribute
extends Attribute<EnclosingMethodAttribute>, ClassElement
permits BoundAttribute.BoundEnclosingMethodAttribute,
UnboundAttribute.UnboundEnclosingMethodAttribute {
/**
* {@return the innermost class that encloses the declaration of the current
* class}
*/
ClassEntry enclosingClass();
/**
* {@return the name and type of the enclosing method, if the class is
* immediately enclosed by a method or constructor}
*/
Optional<NameAndTypeEntry> enclosingMethod();
/**
* {@return the name of the enclosing method, if the class is
* immediately enclosed by a method or constructor}
*/
default Optional<Utf8Entry> enclosingMethodName() {
return enclosingMethod().map(NameAndTypeEntry::name);
}
/**
* {@return the type of the enclosing method, if the class is
* immediately enclosed by a method or constructor}
*/
default Optional<Utf8Entry> enclosingMethodType() {
return enclosingMethod().map(NameAndTypeEntry::type);
}
/**
* {@return the type of the enclosing method, if the class is
* immediately enclosed by a method or constructor}
*/
default Optional<MethodTypeDesc> enclosingMethodTypeSymbol() {
return enclosingMethodType().map(n -> MethodTypeDesc.ofDescriptor(n.stringValue()));
}
/**
* {@return an {@code EnclosingMethod} attribute}
* @param className the class name
* @param method the name and type of the enclosing method
*/
static EnclosingMethodAttribute of(ClassEntry className,
Optional<NameAndTypeEntry> method) {
return new UnboundAttribute.UnboundEnclosingMethodAttribute(className, method.orElse(null));
}
/**
* {@return an {@code EnclosingMethod} attribute}
* @param className the class name
* @param methodName the name of the enclosing method
* @param methodType the type of the enclosing method
*/
static EnclosingMethodAttribute of(ClassDesc className,
Optional<String> methodName,
Optional<MethodTypeDesc> methodType) {
return new UnboundAttribute.UnboundEnclosingMethodAttribute(
TemporaryConstantPool.INSTANCE.classEntry(className),
methodName.isPresent() && methodType.isPresent()
? TemporaryConstantPool.INSTANCE.nameAndTypeEntry(methodName.get(), methodType.get())
: null);
}
}

View File

@ -0,0 +1,85 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models the {@code Exceptions} attribute {@jvms 4.7.5}, which can appear on
* methods, and records the exceptions declared to be thrown by this method.
* Delivered as a {@link MethodElement} when traversing the elements of a
* {@link jdk.internal.classfile.MethodModel}.
*/
public sealed interface ExceptionsAttribute
extends Attribute<ExceptionsAttribute>, MethodElement
permits BoundAttribute.BoundExceptionsAttribute,
UnboundAttribute.UnboundExceptionsAttribute {
/**
* {@return the exceptions declared to be thrown by this method}
*/
List<ClassEntry> exceptions();
/**
* {@return an {@code Exceptions} attribute}
* @param exceptions the checked exceptions that may be thrown from this method
*/
static ExceptionsAttribute of(List<ClassEntry> exceptions) {
return new UnboundAttribute.UnboundExceptionsAttribute(exceptions);
}
/**
* {@return an {@code Exceptions} attribute}
* @param exceptions the checked exceptions that may be thrown from this method
*/
static ExceptionsAttribute of(ClassEntry... exceptions) {
return of(List.of(exceptions));
}
/**
* {@return an {@code Exceptions} attribute}
* @param exceptions the checked exceptions that may be thrown from this method
*/
static ExceptionsAttribute ofSymbols(List<ClassDesc> exceptions) {
return of(Util.entryList(exceptions));
}
/**
* {@return an {@code Exceptions} attribute}
* @param exceptions the checked exceptions that may be thrown from this method
*/
static ExceptionsAttribute ofSymbols(ClassDesc... exceptions) {
return ofSymbols(Arrays.asList(exceptions));
}
}

View File

@ -0,0 +1,120 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Optional;
import java.util.Set;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single inner class in the {@link InnerClassesAttribute}.
*/
public sealed interface InnerClassInfo
permits UnboundAttribute.UnboundInnerClassInfo {
/**
* {@return the class described by this inner class description}
*/
ClassEntry innerClass();
/**
* {@return the class or interface of which this class is a member, if it is a
* member of a class or interface}
*/
Optional<ClassEntry> outerClass();
/**
* {@return the name of the class or interface of which this class is a
* member, if it is a member of a class or interface}
*/
Optional<Utf8Entry> innerName();
/**
* {@return a bit mask of flags denoting access permissions and properties
* of the inner class}
*/
int flagsMask();
/**
* {@return a set of flag enums denoting access permissions and properties
* of the inner class}
*/
default Set<AccessFlag> flags() {
return AccessFlag.maskToAccessFlags(flagsMask(), AccessFlag.Location.INNER_CLASS);
}
/**
* {@return whether a specific access flag is set}
* @param flag the access flag
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.INNER_CLASS, flagsMask(), flag);
}
/**
* {@return an inner class description}
* @param innerClass the inner class being described
* @param outerClass the class containing the inner class, if any
* @param innerName the name of the inner class, if it is not anonymous
* @param flags the inner class access flags
*/
static InnerClassInfo of(ClassEntry innerClass, Optional<ClassEntry> outerClass,
Optional<Utf8Entry> innerName, int flags) {
return new UnboundAttribute.UnboundInnerClassInfo(innerClass, outerClass, innerName, flags);
}
/**
* {@return an inner class description}
* @param innerClass the inner class being described
* @param outerClass the class containing the inner class, if any
* @param innerName the name of the inner class, if it is not anonymous
* @param flags the inner class access flags
*/
static InnerClassInfo of(ClassDesc innerClass, Optional<ClassDesc> outerClass, Optional<String> innerName, int flags) {
return new UnboundAttribute.UnboundInnerClassInfo(TemporaryConstantPool.INSTANCE.classEntry(innerClass),
outerClass.map(TemporaryConstantPool.INSTANCE::classEntry),
innerName.map(TemporaryConstantPool.INSTANCE::utf8Entry),
flags);
}
/**
* {@return an inner class description}
* @param innerClass the inner class being described
* @param outerClass the class containing the inner class, if any
* @param innerName the name of the inner class, if it is not anonymous
* @param flags the inner class access flags
*/
static InnerClassInfo of(ClassDesc innerClass, Optional<ClassDesc> outerClass, Optional<String> innerName, AccessFlag... flags) {
return of(innerClass, outerClass, innerName, Util.flagsToBits(AccessFlag.Location.INNER_CLASS, flags));
}
}

View File

@ -0,0 +1,66 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code InnerClasses} attribute {@jvms 4.7.6}, which can
* appear on classes, and records which classes referenced by this classfile
* are inner classes. Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface InnerClassesAttribute
extends Attribute<InnerClassesAttribute>, ClassElement
permits BoundAttribute.BoundInnerClassesAttribute,
UnboundAttribute.UnboundInnerClassesAttribute {
/**
* {@return the inner classes used by this class}
*/
List<InnerClassInfo> classes();
/**
* {@return an {@code InnerClasses} attribute}
* @param innerClasses descriptions of the inner classes
*/
static InnerClassesAttribute of(List<InnerClassInfo> innerClasses) {
return new UnboundAttribute.UnboundInnerClassesAttribute(innerClasses);
}
/**
* {@return an {@code InnerClasses} attribute}
* @param innerClasses descriptions of the inner classes
*/
static InnerClassesAttribute of(InnerClassInfo... innerClasses) {
return new UnboundAttribute.UnboundInnerClassesAttribute(List.of(innerClasses));
}
}

View File

@ -0,0 +1,54 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single line number in the {@link LineNumberTableAttribute}.
*/
public sealed interface LineNumberInfo
permits UnboundAttribute.UnboundLineNumberInfo {
/**
* {@return the index into the code array at which the code for this line
* begins}
*/
int startPc();
/**
* {@return the line number within the original source file}
*/
int lineNumber();
/**
* {@return a line number description}
* @param startPc the starting index of the code array for this line
* @param lineNumber the line number within the original source file
*/
public static LineNumberInfo of(int startPc, int lineNumber) {
return new UnboundAttribute.UnboundLineNumberInfo(startPc, lineNumber);
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code LineNumberTable} attribute {@jvms 4.7.12}, which can appear
* on a {@code Code} attribute, and records the mapping between indexes into
* the code table and line numbers in the source file.
* Delivered as a {@link jdk.internal.classfile.instruction.LineNumber} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.Option#processLineNumbers(boolean)} option.
*/
public sealed interface LineNumberTableAttribute
extends Attribute<LineNumberTableAttribute>
permits BoundAttribute.BoundLineNumberTableAttribute,
UnboundAttribute.UnboundLineNumberTableAttribute {
/**
* {@return the table mapping bytecode offsets to source line numbers}
*/
List<LineNumberInfo> lineNumbers();
/**
* {@return a {@code LineNumberTable} attribute}
* @param lines the line number descriptions
*/
static LineNumberTableAttribute of(List<LineNumberInfo> lines) {
return new UnboundAttribute.UnboundLineNumberTableAttribute(lines);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundLocalVariable;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single local variable in the {@link LocalVariableTableAttribute}.
*/
public sealed interface LocalVariableInfo
permits UnboundAttribute.UnboundLocalVariableInfo, BoundLocalVariable {
/**
* {@return the index into the code array (inclusive) at which the scope of
* this variable begins}
*/
int startPc();
/**
* {@return the length of the region of the code array in which this
* variable is in scope.}
*/
int length();
/**
* {@return the name of the local variable}
*/
Utf8Entry name();
/**
* {@return the field descriptor of the local variable}
*/
Utf8Entry type();
/**
* {@return the field descriptor of the local variable}
*/
default ClassDesc typeSymbol() {
return ClassDesc.ofDescriptor(type().stringValue());
}
/**
* {@return the index into the local variable array of the current frame
* which holds this local variable}
*/
int slot();
}

View File

@ -0,0 +1,57 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.util.List;
/**
* Models the {@code LocalVariableTable} attribute {@jvms 4.7.13}, which can appear
* on a {@code Code} attribute, and records debug information about local
* variables.
* Delivered as a {@link jdk.internal.classfile.instruction.LocalVariable} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.Option#processDebug(boolean)} option.
*/
public sealed interface LocalVariableTableAttribute
extends Attribute<LocalVariableTableAttribute>
permits BoundAttribute.BoundLocalVariableTableAttribute, UnboundAttribute.UnboundLocalVariableTableAttribute {
/**
* {@return debug information for the local variables in this method}
*/
List<LocalVariableInfo> localVariables();
/**
* {@return a {@code LocalVariableTable} attribute}
* @param locals the local variable descriptions
*/
static LocalVariableTableAttribute of(List<LocalVariableInfo> locals) {
return new UnboundAttribute.UnboundLocalVariableTableAttribute(locals);
}
}

View File

@ -0,0 +1,65 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundLocalVariableType;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single local variable in the {@link LocalVariableTypeTableAttribute}.
*/
public sealed interface LocalVariableTypeInfo
permits UnboundAttribute.UnboundLocalVariableTypeInfo, BoundLocalVariableType {
/**
* {@return the index into the code array (inclusive) at which the scope of
* this variable begins}
*/
int startPc();
/**
* {@return the length of the region of the code array in which this
* variable is in scope.}
*/
int length();
/**
* {@return the name of the local variable}
*/
Utf8Entry name();
/**
* {@return the field signature of the local variable}
*/
Utf8Entry signature();
/**
* {@return the index into the local variable array of the current frame
* which holds this local variable}
*/
int slot();
}

View File

@ -0,0 +1,58 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.util.List;
/**
* Models the {@code LocalVariableTypeTable} attribute {@jvms 4.7.14}, which can appear
* on a {@code Code} attribute, and records debug information about local
* variables.
* Delivered as a {@link jdk.internal.classfile.instruction.LocalVariable} when traversing the
* elements of a {@link jdk.internal.classfile.CodeModel}, according to the setting of the
* {@link jdk.internal.classfile.Classfile.Option#processLineNumbers(boolean)} option.
*/
public sealed interface LocalVariableTypeTableAttribute
extends Attribute<LocalVariableTypeTableAttribute>
permits BoundAttribute.BoundLocalVariableTypeTableAttribute, UnboundAttribute.UnboundLocalVariableTypeTableAttribute {
/**
* {@return debug information for the local variables in this method}
*/
List<LocalVariableTypeInfo> localVariableTypes();
/**
* {@return a {@code LocalVariableTypeTable} attribute}
* @param locals the local variable descriptions
*/
static LocalVariableTypeTableAttribute of(List<LocalVariableTypeInfo> locals) {
return new UnboundAttribute.UnboundLocalVariableTypeTableAttribute(locals);
}
}

View File

@ -0,0 +1,101 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.Optional;
import java.util.Set;
import jdk.internal.classfile.constantpool.Utf8Entry;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.Classfile;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single method parameter in the {@link MethodParametersAttribute}.
*/
public sealed interface MethodParameterInfo
permits UnboundAttribute.UnboundMethodParameterInfo {
/**
* The name of the method parameter, if there is one.
*
* @return the parameter name, if it has one
*/
Optional<Utf8Entry> name();
/**
* Parameter access flags for this parameter, as a bit mask. Valid
* parameter flags include {@link Classfile#ACC_FINAL},
* {@link Classfile#ACC_SYNTHETIC}, and {@link Classfile#ACC_MANDATED}.
*
* @return the access flags, as a bit mask
*/
int flagsMask();
/**
* Parameter access flags for this parameter.
*
* @return the access flags, as a bit mask
*/
default Set<AccessFlag> flags() {
return AccessFlag.maskToAccessFlags(flagsMask(), AccessFlag.Location.METHOD_PARAMETER);
}
/**
* {@return whether the method parameter has a specific flag set}
* @param flag the method parameter flag
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.METHOD_PARAMETER, flagsMask(), flag);
}
/**
* {@return a method parameter description}
* @param name the method parameter name
* @param flags the method parameter access flags
*/
static MethodParameterInfo of(Optional<Utf8Entry> name, int flags) {
return new UnboundAttribute.UnboundMethodParameterInfo(name, flags);
}
/**
* {@return a method parameter description}
* @param name the method parameter name
* @param flags the method parameter access flags
*/
static MethodParameterInfo of(Optional<String> name, AccessFlag... flags) {
return of(name.map(TemporaryConstantPool.INSTANCE::utf8Entry), Util.flagsToBits(AccessFlag.Location.METHOD_PARAMETER, flags));
}
/**
* {@return a method parameter description}
* @param name the method parameter name
* @param flags the method parameter access flags
*/
static MethodParameterInfo ofParameter(Optional<String> name, int flags) {
return of(name.map(TemporaryConstantPool.INSTANCE::utf8Entry), flags);
}
}

View File

@ -0,0 +1,67 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code MethodParameters} attribute {@jvms 4.7.24}, which can
* appear on methods, and records optional information about the method's
* parameters. Delivered as a {@link jdk.internal.classfile.MethodElement} when
* traversing the elements of a {@link jdk.internal.classfile.MethodModel}.
*/
public sealed interface MethodParametersAttribute
extends Attribute<MethodParametersAttribute>, MethodElement
permits BoundAttribute.BoundMethodParametersAttribute,
UnboundAttribute.UnboundMethodParametersAttribute {
/**
* {@return information about the parameters of the method} The i'th entry
* in the list correponds to the i'th parameter in the method declaration.
*/
List<MethodParameterInfo> parameters();
/**
* {@return a {@code MethodParameters} attribute}
* @param parameters the method parameter descriptions
*/
static MethodParametersAttribute of(List<MethodParameterInfo> parameters) {
return new UnboundAttribute.UnboundMethodParametersAttribute(parameters);
}
/**
* {@return a {@code MethodParameters} attribute}
* @param parameters the method parameter descriptions
*/
static MethodParametersAttribute of(MethodParameterInfo... parameters) {
return of(List.of(parameters));
}
}

View File

@ -0,0 +1,181 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Collection;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.java.lang.constant.ModuleDesc;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
import jdk.internal.classfile.impl.ModuleAttributeBuilderImpl;
import jdk.internal.classfile.impl.Util;
/**
* Models the {@code Module} attribute {@jvms 4.7.25}, which can
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface ModuleAttribute
extends Attribute<ModuleAttribute>, ClassElement
permits BoundAttribute.BoundModuleAttribute, UnboundAttribute.UnboundModuleAttribute {
/**
* {@return the name of the module}
*/
ModuleEntry moduleName();
/**
* {@return the the module flags of the module, as a bit mask}
*/
int moduleFlagsMask();
/**
* {@return the the module flags of the module, as a set of enum constants}
*/
default Set<AccessFlag> moduleFlags() {
return AccessFlag.maskToAccessFlags(moduleFlagsMask(), AccessFlag.Location.MODULE);
}
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.MODULE, moduleFlagsMask(), flag);
}
/**
* {@return version of the module, if present}
*/
Optional<Utf8Entry> moduleVersion();
/**
* {@return the modules required by this module}
*/
List<ModuleRequireInfo> requires();
/**
* {@return the packages exported by this module}
*/
List<ModuleExportInfo> exports();
/**
* {@return the packages opened by this module}
*/
List<ModuleOpenInfo> opens();
/**
* {@return the services used by this module} Services may be discovered via
* {@link java.util.ServiceLoader}.
*/
List<ClassEntry> uses();
/**
* {@return the service implementations provided by this module}
*/
List<ModuleProvideInfo> provides();
/**
* {@return a {@code Module} attribute}
*
* @param moduleName the module name
* @param moduleFlags the module flags
* @param moduleVersion the module version
* @param requires the required packages
* @param exports the exported packages
* @param opens the opened packages
* @param uses the consumed services
* @param provides the provided services
*/
static ModuleAttribute of(ModuleEntry moduleName, int moduleFlags,
Utf8Entry moduleVersion,
Collection<ModuleRequireInfo> requires,
Collection<ModuleExportInfo> exports,
Collection<ModuleOpenInfo> opens,
Collection<ClassEntry> uses,
Collection<ModuleProvideInfo> provides) {
return new UnboundAttribute.UnboundModuleAttribute(moduleName, moduleFlags, moduleVersion, requires, exports, opens, uses, provides);
}
/**
* {@return a {@code Module} attribute}
*
* @param moduleName the module name
* @param attrHandler a handler that receives a {@link ModuleAttributeBuilder}
*/
static ModuleAttribute of(ModuleDesc moduleName,
Consumer<ModuleAttributeBuilder> attrHandler) {
var mb = new ModuleAttributeBuilderImpl(moduleName);
attrHandler.accept(mb);
return mb.build();
}
public sealed interface ModuleAttributeBuilder
permits ModuleAttributeBuilderImpl {
ModuleAttributeBuilder moduleName(ModuleDesc moduleName);
ModuleAttributeBuilder moduleFlags(int flagsMask);
default ModuleAttributeBuilder moduleFlags(AccessFlag... moduleFlags) {
return moduleFlags(Util.flagsToBits(AccessFlag.Location.MODULE, moduleFlags));
}
ModuleAttributeBuilder moduleVersion(String version);
ModuleAttributeBuilder requires(ModuleDesc module, int requiresFlagsMask, String version);
default ModuleAttributeBuilder requires(ModuleDesc module, Collection<AccessFlag> requiresFlags, String version) {
return requires(module, Util.flagsToBits(AccessFlag.Location.MODULE_REQUIRES, requiresFlags), version);
}
ModuleAttributeBuilder requires(ModuleRequireInfo requires);
ModuleAttributeBuilder exports(PackageDesc pkge, int exportsFlagsMask, ModuleDesc... exportsToModules);
default ModuleAttributeBuilder exports(PackageDesc pkge, Collection<AccessFlag> exportsFlags, ModuleDesc... exportsToModules) {
return exports(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportsFlags), exportsToModules);
}
ModuleAttributeBuilder exports(ModuleExportInfo exports);
ModuleAttributeBuilder opens(PackageDesc pkge, int opensFlagsMask, ModuleDesc... opensToModules);
default ModuleAttributeBuilder opens(PackageDesc pkge, Collection<AccessFlag> opensFlags, ModuleDesc... opensToModules) {
return opens(pkge, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensToModules);
}
ModuleAttributeBuilder opens(ModuleOpenInfo opens);
ModuleAttributeBuilder uses(ClassDesc service);
ModuleAttributeBuilder uses(ClassEntry uses);
ModuleAttributeBuilder provides(ClassDesc service, ClassDesc... implClasses);
ModuleAttributeBuilder provides(ModuleProvideInfo provides);
ModuleAttribute build();
}
}

View File

@ -0,0 +1,175 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.java.lang.constant.ModuleDesc;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.Classfile;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single "exports" declaration in the {@link jdk.internal.classfile.attribute.ModuleAttribute}.
*/
public sealed interface ModuleExportInfo
permits UnboundAttribute.UnboundModuleExportInfo {
/**
* {@return the exported package}
*/
PackageEntry exportedPackage();
/**
* {@return the flags associated with this export declaration, as a bit mask}
* Valid flags include {@link Classfile#ACC_SYNTHETIC} and
* {@link Classfile#ACC_MANDATED}.
*/
int exportsFlagsMask();
/**
* {@return the flags associated with this export declaration, as a set of
* flag values}
*/
default Set<AccessFlag> exportsFlags() {
return AccessFlag.maskToAccessFlags(exportsFlagsMask(), AccessFlag.Location.MODULE_EXPORTS);
}
/**
* {@return the list of modules to which this package is exported, if it is a
* qualified export}
*/
List<ModuleEntry> exportsTo();
/**
* {@return whether the module has the specified access flag set}
* @param flag the access flag
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.MODULE_EXPORTS, exportsFlagsMask(), flag);
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags, as a bitmask
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageEntry exports, int exportFlags,
List<ModuleEntry> exportsTo) {
return new UnboundAttribute.UnboundModuleExportInfo(exports, exportFlags, exportsTo);
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageEntry exports, Collection<AccessFlag> exportFlags,
List<ModuleEntry> exportsTo) {
return of(exports, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportFlags), exportsTo);
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags, as a bitmask
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageEntry exports,
int exportFlags,
ModuleEntry... exportsTo) {
return of(exports, exportFlags, List.of(exportsTo));
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageEntry exports,
Collection<AccessFlag> exportFlags,
ModuleEntry... exportsTo) {
return of(exports, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportFlags), exportsTo);
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags, as a bitmask
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageDesc exports, int exportFlags,
List<ModuleDesc> exportsTo) {
return of(TemporaryConstantPool.INSTANCE.packageEntry(TemporaryConstantPool.INSTANCE.utf8Entry(exports.packageInternalName())),
exportFlags,
Util.moduleEntryList(exportsTo));
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageDesc exports, Collection<AccessFlag> exportFlags,
List<ModuleDesc> exportsTo) {
return of(exports, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportFlags), exportsTo);
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags, as a bitmask
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageDesc exports,
int exportFlags,
ModuleDesc... exportsTo) {
return of(exports, exportFlags, List.of(exportsTo));
}
/**
* {@return a module export description}
* @param exports the exported package
* @param exportFlags the export flags
* @param exportsTo the modules to which this package is exported
*/
static ModuleExportInfo of(PackageDesc exports,
Collection<AccessFlag> exportFlags,
ModuleDesc... exportsTo) {
return of(exports, Util.flagsToBits(AccessFlag.Location.MODULE_EXPORTS, exportFlags), exportsTo);
}
}

View File

@ -0,0 +1,65 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.java.lang.constant.ModuleDesc;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models hash information for a single module in the {@link jdk.internal.classfile.attribute.ModuleHashesAttribute}.
*/
public sealed interface ModuleHashInfo
permits UnboundAttribute.UnboundModuleHashInfo {
/**
* {@return the name of the related module}
*/
ModuleEntry moduleName();
/**
* {@return the hash of the related module}
*/
byte[] hash();
/**
* {@return a module hash description}
* @param moduleName the module name
* @param hash the hash value
*/
static ModuleHashInfo of(ModuleEntry moduleName, byte[] hash) {
return new UnboundAttribute.UnboundModuleHashInfo(moduleName, hash);
}
/**
* {@return a module hash description}
* @param moduleDesc the module name
* @param hash the hash value
*/
static ModuleHashInfo of(ModuleDesc moduleDesc, byte[] hash) {
return new UnboundAttribute.UnboundModuleHashInfo(TemporaryConstantPool.INSTANCE.moduleEntry(TemporaryConstantPool.INSTANCE.utf8Entry(moduleDesc.moduleName())), hash);
}
}

View File

@ -0,0 +1,120 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import java.util.List;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ModuleHashes} attribute, which can
* appear on classes that represent module descriptors. This is a JDK-specific
* attribute, which captures the hashes of a set of co-delivered modules.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*
* <p>The specification of the {@code ModuleHashes} attribute is:
* <pre> {@code
*
* ModuleHashes_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleHashes"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with algorithm name
* u2 algorithm_index;
*
* // the number of entries in the hashes table
* u2 hashes_count;
* { u2 module_name_index (index to CONSTANT_Module_info structure)
* u2 hash_length;
* u1 hash[hash_length];
* } hashes[hashes_count];
*
* }
* } </pre>
*/
public sealed interface ModuleHashesAttribute
extends Attribute<ModuleHashesAttribute>, ClassElement
permits BoundAttribute.BoundModuleHashesAttribute, UnboundAttribute.UnboundModuleHashesAttribute {
/**
* {@return the algorithm name used to compute the hash}
*/
Utf8Entry algorithm();
/**
* {@return the hash information about related modules}
*/
List<ModuleHashInfo> hashes();
/**
* {@return a {@code ModuleHashes} attribute}
* @param algorithm the hashing algorithm
* @param hashes the hash descriptions
*/
static ModuleHashesAttribute of(String algorithm,
List<ModuleHashInfo> hashes) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(algorithm), hashes);
}
/**
* {@return a {@code ModuleHashes} attribute}
* @param algorithm the hashing algorithm
* @param hashes the hash descriptions
*/
static ModuleHashesAttribute of(String algorithm,
ModuleHashInfo... hashes) {
return of(algorithm, List.of(hashes));
}
/**
* {@return a {@code ModuleHashes} attribute}
* @param algorithm the hashing algorithm
* @param hashes the hash descriptions
*/
static ModuleHashesAttribute of(Utf8Entry algorithm,
List<ModuleHashInfo> hashes) {
return new UnboundAttribute.UnboundModuleHashesAttribute(algorithm, hashes);
}
/**
* {@return a {@code ModuleHashes} attribute}
* @param algorithm the hashing algorithm
* @param hashes the hash descriptions
*/
static ModuleHashesAttribute of(Utf8Entry algorithm,
ModuleHashInfo... hashes) {
return of(algorithm, List.of(hashes));
}
}

View File

@ -0,0 +1,66 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ModuleMainClass} attribute {@jvms 4.7.27}, which can
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface ModuleMainClassAttribute
extends Attribute<ModuleMainClassAttribute>, ClassElement
permits BoundAttribute.BoundModuleMainClassAttribute, UnboundAttribute.UnboundModuleMainClassAttribute {
/**
* {@return main class for this module}
*/
ClassEntry mainClass();
/**
* {@return a {@code ModuleMainClass} attribute}
* @param mainClass the main class
*/
static ModuleMainClassAttribute of(ClassEntry mainClass) {
return new UnboundAttribute.UnboundModuleMainClassAttribute(mainClass);
}
/**
* {@return a {@code ModuleMainClass} attribute}
* @param mainClass the main class
*/
static ModuleMainClassAttribute of(ClassDesc mainClass) {
return new UnboundAttribute.UnboundModuleMainClassAttribute(TemporaryConstantPool.INSTANCE.classEntry(mainClass));
}
}

View File

@ -0,0 +1,172 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.java.lang.constant.ModuleDesc;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single "opens" declaration in the {@link jdk.internal.classfile.attribute.ModuleAttribute}.
*/
public sealed interface ModuleOpenInfo
permits UnboundAttribute.UnboundModuleOpenInfo {
/**
* {@return the package being opened}
*/
PackageEntry openedPackage();
/**
* {@return the flags associated with this open declaration, as a bit mask}
* Valid flags include {@link jdk.internal.classfile.Classfile#ACC_SYNTHETIC} and
* {@link jdk.internal.classfile.Classfile#ACC_MANDATED}
*/
int opensFlagsMask();
default Set<AccessFlag> opensFlags() {
return AccessFlag.maskToAccessFlags(opensFlagsMask(), AccessFlag.Location.MODULE_OPENS);
}
/**
* {@return whether the specified access flag is set}
* @param flag the access flag
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.MODULE_OPENS, opensFlagsMask(), flag);
}
/**
* The list of modules to which this package is opened, if it is a
* qualified open.
*
* @return the modules to which this package is opened
*/
List<ModuleEntry> opensTo();
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageEntry opens, int opensFlags,
List<ModuleEntry> opensTo) {
return new UnboundAttribute.UnboundModuleOpenInfo(opens, opensFlags, opensTo);
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageEntry opens, Collection<AccessFlag> opensFlags,
List<ModuleEntry> opensTo) {
return of(opens, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensTo);
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageEntry opens,
int opensFlags,
ModuleEntry... opensTo) {
return of(opens, opensFlags, List.of(opensTo));
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageEntry opens,
Collection<AccessFlag> opensFlags,
ModuleEntry... opensTo) {
return of(opens, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensTo);
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageDesc opens, int opensFlags,
List<ModuleDesc> opensTo) {
return of(TemporaryConstantPool.INSTANCE.packageEntry(TemporaryConstantPool.INSTANCE.utf8Entry(opens.packageInternalName())),
opensFlags,
Util.moduleEntryList(opensTo));
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageDesc opens, Collection<AccessFlag> opensFlags,
List<ModuleDesc> opensTo) {
return of(opens, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensTo);
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageDesc opens,
int opensFlags,
ModuleDesc... opensTo) {
return of(opens, opensFlags, List.of(opensTo));
}
/**
* {@return a module open description}
* @param opens the package to open
* @param opensFlags the open flags
* @param opensTo the packages to which this package is opened, if it is a qualified open
*/
static ModuleOpenInfo of(PackageDesc opens,
Collection<AccessFlag> opensFlags,
ModuleDesc... opensTo) {
return of(opens, Util.flagsToBits(AccessFlag.Location.MODULE_OPENS, opensFlags), opensTo);
}
}

View File

@ -0,0 +1,91 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.impl.BoundAttribute;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.constantpool.PackageEntry;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ModulePackages} attribute {@jvms 4.7.26}, which can
* appear on classes that represent module descriptors.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface ModulePackagesAttribute
extends Attribute<ModulePackagesAttribute>, ClassElement
permits BoundAttribute.BoundModulePackagesAttribute,
UnboundAttribute.UnboundModulePackagesAttribute {
/**
* {@return the packages that are opened or exported by this module}
*/
List<PackageEntry> packages();
/**
* {@return a {@code ModulePackages} attribute}
* @param packages the packages
*/
static ModulePackagesAttribute of(List<PackageEntry> packages) {
return new UnboundAttribute.UnboundModulePackagesAttribute(packages);
}
/**
* {@return a {@code ModulePackages} attribute}
* @param packages the packages
*/
static ModulePackagesAttribute of(PackageEntry... packages) {
return of(List.of(packages));
}
/**
* {@return a {@code ModulePackages} attribute}
* @param packages the packages
*/
static ModulePackagesAttribute ofNames(List<PackageDesc> packages) {
var p = new PackageEntry[packages.size()];
for (int i = 0; i < packages.size(); i++) {
p[i] = TemporaryConstantPool.INSTANCE.packageEntry(TemporaryConstantPool.INSTANCE.utf8Entry(packages.get(i).packageInternalName()));
}
return of(p);
}
/**
* {@return a {@code ModulePackages} attribute}
* @param packages the packages
*/
static ModulePackagesAttribute ofNames(PackageDesc... packages) {
// List view, since ref to packages is temporary
return ofNames(Arrays.asList(packages));
}
}

View File

@ -0,0 +1,92 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single "provides" declaration in the {@link jdk.internal.classfile.attribute.ModuleAttribute}.
*/
public sealed interface ModuleProvideInfo
permits UnboundAttribute.UnboundModuleProvideInfo {
/**
* {@return the service interface representing the provided service}
*/
ClassEntry provides();
/**
* {@return the classes providing the service implementation}
*/
List<ClassEntry> providesWith();
/**
* {@return a service provision description}
* @param provides the service class interface
* @param providesWith the service class implementations
*/
static ModuleProvideInfo of(ClassEntry provides,
List<ClassEntry> providesWith) {
return new UnboundAttribute.UnboundModuleProvideInfo(provides, providesWith);
}
/**
* {@return a service provision description}
* @param provides the service class interface
* @param providesWith the service class implementations
*/
static ModuleProvideInfo of(ClassEntry provides,
ClassEntry... providesWith) {
return of(provides, List.of(providesWith));
}
/**
* {@return a service provision description}
* @param provides the service class interface
* @param providesWith the service class implementations
*/
static ModuleProvideInfo of(ClassDesc provides,
List<ClassDesc> providesWith) {
return of(TemporaryConstantPool.INSTANCE.classEntry(provides), Util.entryList(providesWith));
}
/**
* {@return a service provision description}
* @param provides the service class interface
* @param providesWith the service class implementations
*/
static ModuleProvideInfo of(ClassDesc provides,
ClassDesc... providesWith) {
// List view, since ref to providesWith is temporary
return of(provides, Arrays.asList(providesWith));
}
}

View File

@ -0,0 +1,115 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import jdk.internal.classfile.constantpool.ModuleEntry;
import jdk.internal.classfile.constantpool.Utf8Entry;
import java.lang.reflect.AccessFlag;
import jdk.internal.classfile.java.lang.constant.ModuleDesc;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models a single "requires" declaration in the {@link jdk.internal.classfile.attribute.ModuleAttribute}.
*/
public sealed interface ModuleRequireInfo
permits UnboundAttribute.UnboundModuleRequiresInfo {
/**
* {@return The module on which the current module depends}
*/
ModuleEntry requires();
/**
* {@return the flags associated with this require declaration, as a bit mask}
* Valid flags include {@link jdk.internal.classfile.Classfile#ACC_TRANSITIVE},
* {@link jdk.internal.classfile.Classfile#ACC_STATIC_PHASE},
* {@link jdk.internal.classfile.Classfile#ACC_SYNTHETIC} and
* {@link jdk.internal.classfile.Classfile#ACC_MANDATED}
*/
int requiresFlagsMask();
default Set<AccessFlag> requiresFlags() {
return AccessFlag.maskToAccessFlags(requiresFlagsMask(), AccessFlag.Location.MODULE_REQUIRES);
}
/**
* {@return the required version of the required module, if present}
*/
Optional<Utf8Entry> requiresVersion();
/**
* {@return whether the specific access flag is set}
* @param flag the access flag
*/
default boolean has(AccessFlag flag) {
return Util.has(AccessFlag.Location.MODULE_REQUIRES, requiresFlagsMask(), flag);
}
/**
* {@return a module requirement description}
* @param requires the required module
* @param requiresFlags the require-specific flags
* @param requiresVersion the required version
*/
static ModuleRequireInfo of(ModuleEntry requires, int requiresFlags, Utf8Entry requiresVersion) {
return new UnboundAttribute.UnboundModuleRequiresInfo(requires, requiresFlags, Optional.ofNullable(requiresVersion));
}
/**
* {@return a module requirement description}
* @param requires the required module
* @param requiresFlags the require-specific flags
* @param requiresVersion the required version
*/
static ModuleRequireInfo of(ModuleEntry requires, Collection<AccessFlag> requiresFlags, Utf8Entry requiresVersion) {
return of(requires, Util.flagsToBits(AccessFlag.Location.MODULE_REQUIRES, requiresFlags), requiresVersion);
}
/**
* {@return a module requirement description}
* @param requires the required module
* @param requiresFlags the require-specific flags
* @param requiresVersion the required version
*/
static ModuleRequireInfo of(ModuleDesc requires, int requiresFlags, String requiresVersion) {
return new UnboundAttribute.UnboundModuleRequiresInfo(TemporaryConstantPool.INSTANCE.moduleEntry(TemporaryConstantPool.INSTANCE.utf8Entry(requires.moduleName())), requiresFlags, Optional.ofNullable(requiresVersion).map(s -> TemporaryConstantPool.INSTANCE.utf8Entry(s)));
}
/**
* {@return a module requirement description}
* @param requires the required module
* @param requiresFlags the require-specific flags
* @param requiresVersion the required version
*/
static ModuleRequireInfo of(ModuleDesc requires, Collection<AccessFlag> requiresFlags, String requiresVersion) {
return of(requires, Util.flagsToBits(AccessFlag.Location.MODULE_REQUIRES, requiresFlags), requiresVersion);
}
}

View File

@ -0,0 +1,85 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ModuleResolution} attribute, which can
* appear on classes that represent module descriptors. This is a JDK-specific
* * attribute, which captures resolution metadata for modules.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*
* <p>The specification of the {@code ModuleResolution} attribute is:
* <pre> {@code
* ModuleResolution_attribute {
* u2 attribute_name_index; // "ModuleResolution"
* u4 attribute_length; // 2
* u2 resolution_flags;
*
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:
*
* // Optional
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
*
* // At most one of:
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
* }
* } </pre>
*/
public sealed interface ModuleResolutionAttribute
extends Attribute<ModuleResolutionAttribute>, ClassElement
permits BoundAttribute.BoundModuleResolutionAttribute, UnboundAttribute.UnboundModuleResolutionAttribute {
/**
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:
*
* // Optional
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
*
* // At most one of:
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
*/
int resolutionFlags();
/**
* {@return a {@code ModuleResolution} attribute}
* @param resolutionFlags the resolution falgs
*/
static ModuleResolutionAttribute of(int resolutionFlags) {
return new UnboundAttribute.UnboundModuleResolutionAttribute(resolutionFlags);
}
}

View File

@ -0,0 +1,79 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code ModuleTarget} attribute, which can
* appear on classes that represent module descriptors. This is a JDK-specific
* attribute, which captures constraints on the target platform.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*
* <p>The specification of the {@code ModuleTarget} attribute is:
* <pre> {@code
* TargetPlatform_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleTarget"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with the target platform
* u2 target_platform_index;
* }
* } </pre>
*/
public sealed interface ModuleTargetAttribute
extends Attribute<ModuleTargetAttribute>, ClassElement
permits BoundAttribute.BoundModuleTargetAttribute, UnboundAttribute.UnboundModuleTargetAttribute {
/**
* {@return the target platform}
*/
Utf8Entry targetPlatform();
/**
* {@return a {@code ModuleTarget} attribute}
* @param targetPlatform the target platform
*/
static ModuleTargetAttribute of(String targetPlatform) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(targetPlatform));
}
/**
* {@return a {@code ModuleTarget} attribute}
* @param targetPlatform the target platform
*/
static ModuleTargetAttribute of(Utf8Entry targetPlatform) {
return new UnboundAttribute.UnboundModuleTargetAttribute(targetPlatform);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code NestHost} attribute {@jvms 4.7.28}, which can
* appear on classes to indicate that this class is a member of a nest.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface NestHostAttribute extends Attribute<NestHostAttribute>, ClassElement
permits BoundAttribute.BoundNestHostAttribute,
UnboundAttribute.UnboundNestHostAttribute {
/**
* {@return the host class of the nest to which this class belongs}
*/
ClassEntry nestHost();
/**
* {@return a {@code NestHost} attribute}
* @param nestHost the host class of the nest
*/
static NestHostAttribute of(ClassEntry nestHost) {
return new UnboundAttribute.UnboundNestHostAttribute(nestHost);
}
/**
* {@return a {@code NestHost} attribute}
* @param nestHost the host class of the nest
*/
static NestHostAttribute of(ClassDesc nestHost) {
return of(TemporaryConstantPool.INSTANCE.classEntry(nestHost));
}
}

View File

@ -0,0 +1,84 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models the {@code NestMembers} attribute {@jvms 4.7.29}, which can
* appear on classes to indicate that this class is the host of a nest.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface NestMembersAttribute extends Attribute<NestMembersAttribute>, ClassElement
permits BoundAttribute.BoundNestMembersAttribute, UnboundAttribute.UnboundNestMembersAttribute {
/**
* {@return the classes belonging to the nest hosted by this class}
*/
List<ClassEntry> nestMembers();
/**
* {@return a {@code NestMembers} attribute}
* @param nestMembers the member classes of the nest
*/
static NestMembersAttribute of(List<ClassEntry> nestMembers) {
return new UnboundAttribute.UnboundNestMembersAttribute(nestMembers);
}
/**
* {@return a {@code NestMembers} attribute}
* @param nestMembers the member classes of the nest
*/
static NestMembersAttribute of(ClassEntry... nestMembers) {
return of(List.of(nestMembers));
}
/**
* {@return a {@code NestMembers} attribute}
* @param nestMembers the member classes of the nest
*/
static NestMembersAttribute ofSymbols(List<ClassDesc> nestMembers) {
return of(Util.entryList(nestMembers));
}
/**
* {@return a {@code NestMembers} attribute}
* @param nestMembers the member classes of the nest
*/
static NestMembersAttribute ofSymbols(ClassDesc... nestMembers) {
// List view, since ref to nestMembers is temporary
return ofSymbols(Arrays.asList(nestMembers));
}
}

View File

@ -0,0 +1,85 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.Arrays;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.classfile.impl.Util;
/**
* Models the {@code PermittedSubclasses} attribute {@jvms 4.7.31}, which can
* appear on classes to indicate which classes may extend this class.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface PermittedSubclassesAttribute
extends Attribute<PermittedSubclassesAttribute>, ClassElement
permits BoundAttribute.BoundPermittedSubclassesAttribute, UnboundAttribute.UnboundPermittedSubclassesAttribute {
/**
* {@return the list of permitted subclasses}
*/
List<ClassEntry> permittedSubclasses();
/**
* {@return a {@code PermittedSubclasses} attribute}
* @param permittedSubclasses the permitted subclasses
*/
static PermittedSubclassesAttribute of(List<ClassEntry> permittedSubclasses) {
return new UnboundAttribute.UnboundPermittedSubclassesAttribute(permittedSubclasses);
}
/**
* {@return a {@code PermittedSubclasses} attribute}
* @param permittedSubclasses the permitted subclasses
*/
static PermittedSubclassesAttribute of(ClassEntry... permittedSubclasses) {
return of(List.of(permittedSubclasses));
}
/**
* {@return a {@code PermittedSubclasses} attribute}
* @param permittedSubclasses the permitted subclasses
*/
static PermittedSubclassesAttribute ofSymbols(List<ClassDesc> permittedSubclasses) {
return of(Util.entryList(permittedSubclasses));
}
/**
* {@return a {@code PermittedSubclasses} attribute}
* @param permittedSubclasses the permitted subclasses
*/
static PermittedSubclassesAttribute ofSymbols(ClassDesc... permittedSubclasses) {
// List view, since ref to nestMembers is temporary
return ofSymbols(Arrays.asList(permittedSubclasses));
}
}

View File

@ -0,0 +1,64 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code Record} attribute {@jvms 4.7.30}, which can
* appear on classes to indicate that this class is a record class.
* Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing the elements of a {@link jdk.internal.classfile.ClassModel}.
*/
public sealed interface RecordAttribute extends Attribute<RecordAttribute>, ClassElement
permits BoundAttribute.BoundRecordAttribute, UnboundAttribute.UnboundRecordAttribute {
/**
* {@return the components of this record class}
*/
List<RecordComponentInfo> components();
/**
* {@return a {@code Record} attribute}
* @param components the record components
*/
static RecordAttribute of(List<RecordComponentInfo> components) {
return new UnboundAttribute.UnboundRecordAttribute(components);
}
/**
* {@return a {@code Record} attribute}
* @param components the record components
*/
static RecordAttribute of(RecordComponentInfo... components) {
return of(List.of(components));
}
}

View File

@ -0,0 +1,109 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.AttributedElement;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundRecordComponentInfo;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models a single record component in the {@link jdk.internal.classfile.attribute.RecordAttribute}.
*/
public sealed interface RecordComponentInfo
extends AttributedElement
permits BoundRecordComponentInfo, UnboundAttribute.UnboundRecordComponentInfo {
/**
* {@return the name of this component}
*/
Utf8Entry name();
/**
* {@return the field descriptor of this component}
*/
Utf8Entry descriptor();
/**
* {@return the field descriptor of this component, as a {@linkplain ClassDesc}}
*/
default ClassDesc descriptorSymbol() {
return ClassDesc.ofDescriptor(descriptor().stringValue());
}
/**
* {@return a record component description}
* @param name the component name
* @param descriptor the component field descriptor
* @param attributes the component attributes
*/
static RecordComponentInfo of(Utf8Entry name,
Utf8Entry descriptor,
List<Attribute<?>> attributes) {
return new UnboundAttribute.UnboundRecordComponentInfo(name, descriptor, attributes);
}
/**
* {@return a record component description}
* @param name the component name
* @param descriptor the component field descriptor
* @param attributes the component attributes
*/
static RecordComponentInfo of(Utf8Entry name,
Utf8Entry descriptor,
Attribute<?>... attributes) {
return of(name, descriptor, List.of(attributes));
}
/**
* {@return a record component description}
* @param name the component name
* @param descriptor the component field descriptor
* @param attributes the component attributes
*/
static RecordComponentInfo of(String name,
ClassDesc descriptor,
List<Attribute<?>> attributes) {
return new UnboundAttribute.UnboundRecordComponentInfo(TemporaryConstantPool.INSTANCE.utf8Entry(name),
TemporaryConstantPool.INSTANCE.utf8Entry(descriptor.descriptorString()),
attributes);
}
/**
* {@return a record component description}
* @param name the component name
* @param descriptor the component field descriptor
* @param attributes the component attributes
*/
static RecordComponentInfo of(String name,
ClassDesc descriptor,
Attribute<?>... attributes) {
return of(name, descriptor, List.of(attributes));
}
}

View File

@ -0,0 +1,66 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.*;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.util.List;
/**
* Models the {@code RuntimeInvisibleAnnotations} attribute {@jvms 4.7.17}, which
* can appear on classes, methods, and fields. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing the corresponding model type.
*/
public sealed interface RuntimeInvisibleAnnotationsAttribute
extends Attribute<RuntimeInvisibleAnnotationsAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeInvisibleAnnotationsAttribute {
/**
* {@return the non-runtime-visible annotations on this class, field, or method}
*/
List<Annotation> annotations();
/**
* {@return a {@code RuntimeInvisibleAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeInvisibleAnnotationsAttribute of(List<Annotation> annotations) {
return new UnboundAttribute.UnboundRuntimeInvisibleAnnotationsAttribute(annotations);
}
/**
* {@return a {@code RuntimeInvisibleAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeInvisibleAnnotationsAttribute of(Annotation... annotations) {
return of(List.of(annotations));
}
}

View File

@ -0,0 +1,61 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Annotation;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.MethodModel;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code RuntimeInvisibleParameterAnnotations} attribute
* {@jvms 4.7.19}, which can appear on methods. Delivered as a {@link
* jdk.internal.classfile.MethodElement} when traversing a {@link MethodModel}.
*/
public sealed interface RuntimeInvisibleParameterAnnotationsAttribute
extends Attribute<RuntimeInvisibleParameterAnnotationsAttribute>, MethodElement
permits BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeInvisibleParameterAnnotationsAttribute {
/**
* {@return the list of annotations corresponding to each method parameter}
* The element at the i'th index corresponds to the annotations on the i'th
* parameter.
*/
List<List<Annotation>> parameterAnnotations();
/**
* {@return a {@code RuntimeInvisibleParameterAnnotations} attribute}
* @param parameterAnnotations a list of parameter annotations for each parameter
*/
static RuntimeInvisibleParameterAnnotationsAttribute of(List<List<Annotation>> parameterAnnotations) {
return new UnboundAttribute.UnboundRuntimeInvisibleParameterAnnotationsAttribute(parameterAnnotations);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.CodeElement;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.TypeAnnotation;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code RuntimeInvisibleTypeAnnotations} attribute {@jvms 4.7.21}, which
* can appear on classes, methods, fields, and code attributes. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement},
* {@link jdk.internal.classfile.MethodElement}, or {@link CodeElement} when traversing
* the corresponding model type.
*/
public sealed interface RuntimeInvisibleTypeAnnotationsAttribute
extends Attribute<RuntimeInvisibleTypeAnnotationsAttribute>,
ClassElement, MethodElement, FieldElement, CodeElement
permits BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeInvisibleTypeAnnotationsAttribute {
/**
* {@return the non-runtime-visible type annotations on parts of this class, field, or method}
*/
List<TypeAnnotation> annotations();
/**
* {@return a {@code RuntimeInvisibleTypeAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeInvisibleTypeAnnotationsAttribute of(List<TypeAnnotation> annotations) {
return new UnboundAttribute.UnboundRuntimeInvisibleTypeAnnotationsAttribute(annotations);
}
/**
* {@return a {@code RuntimeInvisibleTypeAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeInvisibleTypeAnnotationsAttribute of(TypeAnnotation... annotations) {
return of(List.of(annotations));
}
}

View File

@ -0,0 +1,66 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.*;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
import java.util.List;
/**
* Models the {@code RuntimeVisibleAnnotations} attribute {@jvms 4.7.16}, which
* can appear on classes, methods, and fields. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing the corresponding model type.
*/
public sealed interface RuntimeVisibleAnnotationsAttribute
extends Attribute<RuntimeVisibleAnnotationsAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeVisibleAnnotationsAttribute {
/**
* {@return the runtime-visible annotations on this class, field, or method}
*/
List<Annotation> annotations();
/**
* {@return a {@code RuntimeVisibleAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeVisibleAnnotationsAttribute of(List<Annotation> annotations) {
return new UnboundAttribute.UnboundRuntimeVisibleAnnotationsAttribute(annotations);
}
/**
* {@return a {@code RuntimeVisibleAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeVisibleAnnotationsAttribute of(Annotation... annotations) {
return of(List.of(annotations));
}
}

View File

@ -0,0 +1,61 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Annotation;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.MethodModel;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code RuntimeVisibleParameterAnnotations} attribute {@jvms 4.7.18}, which
* can appear on methods. Delivered as a {@link jdk.internal.classfile.MethodElement}
* when traversing a {@link MethodModel}.
*/
public sealed interface RuntimeVisibleParameterAnnotationsAttribute
extends Attribute<RuntimeVisibleParameterAnnotationsAttribute>, MethodElement
permits BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeVisibleParameterAnnotationsAttribute {
/**
* {@return the list of annotations corresponding to each method parameter}
* The element at the i'th index corresponds to the annotations on the i'th
* parameter.
*/
List<List<Annotation>> parameterAnnotations();
/**
* {@return a {@code RuntimeVisibleParameterAnnotations} attribute}
* @param parameterAnnotations a list of parameter annotations for each parameter
*/
static RuntimeVisibleParameterAnnotationsAttribute of(List<List<Annotation>> parameterAnnotations) {
return new UnboundAttribute.UnboundRuntimeVisibleParameterAnnotationsAttribute(parameterAnnotations);
}
}

View File

@ -0,0 +1,72 @@
/*
* 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.CodeElement;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.TypeAnnotation;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code RuntimeVisibleTypeAnnotations} attribute {@jvms 4.7.20}, which
* can appear on classes, methods, fields, and code attributes. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement},
* {@link jdk.internal.classfile.MethodElement}, or {@link CodeElement} when traversing
* the corresponding model type.
*/
public sealed interface RuntimeVisibleTypeAnnotationsAttribute
extends Attribute<RuntimeVisibleTypeAnnotationsAttribute>,
ClassElement, MethodElement, FieldElement, CodeElement
permits BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute,
UnboundAttribute.UnboundRuntimeVisibleTypeAnnotationsAttribute {
/**
* {@return the runtime-visible type annotations on parts of this class, field, or method}
*/
List<TypeAnnotation> annotations();
/**
* {@return a {@code RuntimeVisibleTypeAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeVisibleTypeAnnotationsAttribute of(List<TypeAnnotation> annotations) {
return new UnboundAttribute.UnboundRuntimeVisibleTypeAnnotationsAttribute(annotations);
}
/**
* {@return a {@code RuntimeVisibleTypeAnnotations} attribute}
* @param annotations the annotations
*/
static RuntimeVisibleTypeAnnotationsAttribute of(TypeAnnotation... annotations) {
return of(List.of(annotations));
}
}

View File

@ -0,0 +1,112 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.ClassSignature;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.MethodSignature;
import jdk.internal.classfile.Signature;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code Signature} attribute {@jvms 4.7.9}, which
* can appear on classes, methods, or fields. Delivered as a
* {@link jdk.internal.classfile.ClassElement}, {@link jdk.internal.classfile.FieldElement}, or
* {@link jdk.internal.classfile.MethodElement} when traversing
* the corresponding model type.
*/
public sealed interface SignatureAttribute
extends Attribute<SignatureAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundSignatureAttribute, UnboundAttribute.UnboundSignatureAttribute {
/**
* {@return the signature for the class, method, or field}
*/
Utf8Entry signature();
/**
* Parse the siganture as a class signature.
* @return the class signature
*/
default ClassSignature asClassSignature() {
return ClassSignature.parseFrom(signature().stringValue());
}
/**
* Parse the signature as a method signature.
* @return the method signature
*/
default MethodSignature asMethodSignature() {
return MethodSignature.parseFrom(signature().stringValue());
}
/**
* Parse the siganture as a type signature.
* @return the type signature
*/
default Signature asTypeSignature() {
return Signature.parseFrom(signature().stringValue());
}
/**
* {@return a {@code Signature} attribute for a class}
* @param classSignature the signature
*/
static SignatureAttribute of(ClassSignature classSignature) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(classSignature.signatureString()));
}
/**
* {@return a {@code Signature} attribute for a method}
* @param methodSignature the signature
*/
static SignatureAttribute of(MethodSignature methodSignature) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(methodSignature.signatureString()));
}
/**
* {@return a {@code Signature} attribute}
* @param signature the signature
*/
static SignatureAttribute of(Signature signature) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(signature.signatureString()));
}
/**
* {@return a {@code Signature} attribute}
* @param signature the signature
*/
static SignatureAttribute of(Utf8Entry signature) {
return new UnboundAttribute.UnboundSignatureAttribute(signature);
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* SourceDebugExtensionAttribute.
*/
public sealed interface SourceDebugExtensionAttribute
extends Attribute<SourceDebugExtensionAttribute>, ClassElement
permits BoundAttribute.BoundSourceDebugExtensionAttribute, UnboundAttribute.UnboundSourceDebugExtensionAttribute {
/**
* {@return the debug extension payload}
*/
byte[] contents();
/**
* {@return a {@code SourceDebugExtension} attribute}
* @param contents the extension contents
*/
static SourceDebugExtensionAttribute of(byte[] contents) {
return new UnboundAttribute.UnboundSourceDebugExtensionAttribute(contents);
}
}

View File

@ -0,0 +1,57 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.ClassModel;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code SourceFile} attribute {@jvms 4.7.10}, which
* can appear on classes. Delivered as a {@link jdk.internal.classfile.ClassElement}
* when traversing a {@link ClassModel}.
*/
public sealed interface SourceFileAttribute
extends Attribute<SourceFileAttribute>, ClassElement
permits BoundAttribute.BoundSourceFileAttribute, UnboundAttribute.UnboundSourceFileAttribute {
/**
* {@return the name of the source file from which this class was compiled}
*/
Utf8Entry sourceFile();
static SourceFileAttribute of(String sourceFile) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(sourceFile));
}
static SourceFileAttribute of(Utf8Entry sourceFile) {
return new UnboundAttribute.UnboundSourceFileAttribute(sourceFile);
}
}

View File

@ -0,0 +1,67 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.ClassModel;
import jdk.internal.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code SourceFile} attribute (@@@ reference needed), which can
* appear on classes. Delivered as a {@link jdk.internal.classfile.ClassElement} when
* traversing a {@link ClassModel}.
*/
public sealed interface SourceIDAttribute
extends Attribute<SourceIDAttribute>, ClassElement
permits BoundAttribute.BoundSourceIDAttribute, UnboundAttribute.UnboundSourceIDAttribute {
/**
* {@return the source id} The source id is the last modified time of the
* source file (as reported by the filesystem, in milliseconds) when the
* classfile is compiled.
*/
Utf8Entry sourceId();
/**
* {@return a {@code SourceID} attribute}
* @param sourceId the source id
*/
static SourceIDAttribute of(Utf8Entry sourceId) {
return new UnboundAttribute.UnboundSourceIDAttribute(sourceId);
}
/**
* {@return a {@code SourceID} attribute}
* @param sourceId the source id
*/
static SourceIDAttribute of(String sourceId) {
return of(TemporaryConstantPool.INSTANCE.utf8Entry(sourceId));
}
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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 jdk.internal.classfile.attribute;
import java.lang.constant.ClassDesc;
import java.util.List;
import jdk.internal.classfile.Label;
import jdk.internal.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.StackMapDecoder;
import jdk.internal.classfile.impl.TemporaryConstantPool;
import static jdk.internal.classfile.Classfile.*;
/**
* Models stack map frame of {@code StackMapTable} attribute {@jvms 4.7.4}.
*/
public sealed interface StackMapFrameInfo
permits StackMapDecoder.StackMapFrameImpl {
int frameType();
Label target();
List<VerificationTypeInfo> locals();
List<VerificationTypeInfo> stack();
public static StackMapFrameInfo of(Label target,
List<VerificationTypeInfo> locals,
List<VerificationTypeInfo> stack) {
return new StackMapDecoder.StackMapFrameImpl(255, target, locals, stack);
}
/**
* The type of a stack value.
*/
sealed interface VerificationTypeInfo {
int tag();
}
/**
* A simple stack value.
*/
public enum SimpleVerificationTypeInfo implements VerificationTypeInfo {
ITEM_TOP(VT_TOP),
ITEM_INTEGER(VT_INTEGER),
ITEM_FLOAT(VT_FLOAT),
ITEM_DOUBLE(VT_DOUBLE),
ITEM_LONG(VT_LONG),
ITEM_NULL(VT_NULL),
ITEM_UNINITIALIZED_THIS(VT_UNINITIALIZED_THIS);
private final int tag;
SimpleVerificationTypeInfo(int tag) {
this.tag = tag;
}
@Override
public int tag() {
return tag;
}
}
/**
* A stack value for an object type.
*/
sealed interface ObjectVerificationTypeInfo extends VerificationTypeInfo
permits StackMapDecoder.ObjectVerificationTypeInfoImpl {
public static ObjectVerificationTypeInfo of(ClassEntry className) {
return new StackMapDecoder.ObjectVerificationTypeInfoImpl(className);
}
public static ObjectVerificationTypeInfo of(ClassDesc classDesc) {
return of(TemporaryConstantPool.INSTANCE.classEntry(classDesc));
}
/**
* {@return the class of the value}
*/
ClassEntry className();
default ClassDesc classSymbol() {
return className().asSymbol();
}
}
/**
* An uninitialized stack value.
*/
sealed interface UninitializedVerificationTypeInfo extends VerificationTypeInfo
permits StackMapDecoder.UninitializedVerificationTypeInfoImpl {
Label newTarget();
public static UninitializedVerificationTypeInfo of(Label newTarget) {
return new StackMapDecoder.UninitializedVerificationTypeInfoImpl(newTarget);
}
}
}

View File

@ -0,0 +1,51 @@
/*
* 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 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 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 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 jdk.internal.classfile.attribute;
import java.util.List;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.CodeElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code StackMapTable} attribute {@jvms 4.7.4}, which can appear
* on a {@code Code} attribute.
*/
public sealed interface StackMapTableAttribute
extends Attribute<StackMapTableAttribute>, CodeElement
permits BoundAttribute.BoundStackMapTableAttribute, UnboundAttribute.UnboundStackMapTableAttribute {
/**
* {@return the stack map frames}
*/
List<StackMapFrameInfo> entries();
public static StackMapTableAttribute of(List<StackMapFrameInfo> entries) {
return new UnboundAttribute.UnboundStackMapTableAttribute(entries);
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.impl.BoundAttribute;
import jdk.internal.classfile.impl.UnboundAttribute;
/**
* Models the {@code Synthetic} attribute {@jvms 4.7.8}, which can appear on
* classes, methods, and fields. Delivered as a {@link ClassElement},
* {@link MethodElement}, or {@link FieldElement} when traversing the elements
* of a corresponding model.
*/
public sealed interface SyntheticAttribute
extends Attribute<SyntheticAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundSyntheticAttribute, UnboundAttribute.UnboundSyntheticAttribute {
/**
* {@return a {@code Synthetic} attribute}
*/
static SyntheticAttribute of() {
return new UnboundAttribute.UnboundSyntheticAttribute();
}
}

View File

@ -0,0 +1,46 @@
/*
* 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 jdk.internal.classfile.attribute;
import jdk.internal.classfile.Attribute;
import jdk.internal.classfile.ClassElement;
import jdk.internal.classfile.FieldElement;
import jdk.internal.classfile.MethodElement;
import jdk.internal.classfile.impl.BoundAttribute;
/**
* Models an unknown attribute on a class, method, or field.
*/
public sealed interface UnknownAttribute
extends Attribute<UnknownAttribute>,
ClassElement, MethodElement, FieldElement
permits BoundAttribute.BoundUnknownAttribute {
/**
* {@return the uninterpreted contents of the attribute payload}
*/
byte[] contents();
}

Some files were not shown because too many files have changed in this diff Show More