mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8215300: additional changes to constants API
Reviewed-by: goetz
This commit is contained in:
parent
a3df1d618e
commit
650f3fc113
12 changed files with 96 additions and 24 deletions
|
@ -1077,8 +1077,8 @@ public final class Double extends Number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, which is the instance
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* itself.
|
* instance, which is the instance itself.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} describing the {@linkplain Double} instance
|
* @return an {@link Optional} describing the {@linkplain Double} instance
|
||||||
* @since 12
|
* @since 12
|
||||||
|
|
|
@ -989,8 +989,8 @@ public final class Float extends Number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, which is the instance
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* itself.
|
* instance, which is the instance itself.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} describing the {@linkplain Float} instance
|
* @return an {@link Optional} describing the {@linkplain Float} instance
|
||||||
* @since 12
|
* @since 12
|
||||||
|
|
|
@ -1838,8 +1838,8 @@ public final class Integer extends Number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, which is the instance
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* itself.
|
* instance, which is the instance itself.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} describing the {@linkplain Integer} instance
|
* @return an {@link Optional} describing the {@linkplain Integer} instance
|
||||||
* @since 12
|
* @since 12
|
||||||
|
|
|
@ -1967,8 +1967,8 @@ public final class Long extends Number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, which is the instance
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* itself.
|
* instance, which is the instance itself.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} describing the {@linkplain Long} instance
|
* @return an {@link Optional} describing the {@linkplain Long} instance
|
||||||
* @since 12
|
* @since 12
|
||||||
|
|
|
@ -3545,8 +3545,8 @@ public final class String
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, which is the instance
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* itself.
|
* instance, which is the instance itself.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} describing the {@linkplain String} instance
|
* @return an {@link Optional} describing the {@linkplain String} instance
|
||||||
* @since 12
|
* @since 12
|
||||||
|
|
|
@ -112,13 +112,13 @@ public interface ClassDesc
|
||||||
*
|
*
|
||||||
* A field type descriptor string for a non-array type is either
|
* A field type descriptor string for a non-array type is either
|
||||||
* a one-letter code corresponding to a primitive type
|
* a one-letter code corresponding to a primitive type
|
||||||
* ({@code J,I,C,S,B,D,F,Z,V}), or the letter {@code L}, followed
|
* ({@code "J", "I", "C", "S", "B", "D", "F", "Z", "V"}), or the letter {@code "L"}, followed
|
||||||
* by the fully qualified binary name of a class, followed by {@code ;}.
|
* by the fully qualified binary name of a class, followed by {@code ";"}.
|
||||||
* A field type descriptor for an array type is the character {@code [}
|
* A field type descriptor for an array type is the character {@code "["}
|
||||||
* followed by the field descriptor for the component type. Examples of
|
* followed by the field descriptor for the component type. Examples of
|
||||||
* valid type descriptor strings include {@code Ljava/lang/String;}, {@code I},
|
* valid type descriptor strings include {@code "Ljava/lang/String;"}, {@code "I"},
|
||||||
* {@code [I}, {@code V}, {@code [Ljava/lang/String;}, etc.
|
* {@code "[I"}, {@code "V"}, {@code "[Ljava/lang/String;"}, etc.
|
||||||
* for more detail.
|
* See JVMS 4.3.2 ("Field Descriptors") for more detail.
|
||||||
*
|
*
|
||||||
* @param descriptor a field descriptor string
|
* @param descriptor a field descriptor string
|
||||||
* @return a {@linkplain ClassDesc} describing the desired class
|
* @return a {@linkplain ClassDesc} describing the desired class
|
||||||
|
@ -126,9 +126,15 @@ public interface ClassDesc
|
||||||
* @throws IllegalArgumentException if the name string is not in the
|
* @throws IllegalArgumentException if the name string is not in the
|
||||||
* correct format
|
* correct format
|
||||||
* @jvms 4.3.2 Field Descriptors
|
* @jvms 4.3.2 Field Descriptors
|
||||||
|
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||||
*/
|
*/
|
||||||
static ClassDesc ofDescriptor(String descriptor) {
|
static ClassDesc ofDescriptor(String descriptor) {
|
||||||
requireNonNull(descriptor);
|
requireNonNull(descriptor);
|
||||||
|
int depth = ConstantUtils.arrayDepth(descriptor);
|
||||||
|
if (depth > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
|
||||||
|
throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions",
|
||||||
|
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
|
||||||
|
}
|
||||||
return (descriptor.length() == 1)
|
return (descriptor.length() == 1)
|
||||||
? new PrimitiveClassDescImpl(descriptor)
|
? new PrimitiveClassDescImpl(descriptor)
|
||||||
: new ReferenceClassDescImpl(descriptor);
|
: new ReferenceClassDescImpl(descriptor);
|
||||||
|
@ -139,8 +145,15 @@ public interface ClassDesc
|
||||||
* is described by this {@linkplain ClassDesc}.
|
* is described by this {@linkplain ClassDesc}.
|
||||||
*
|
*
|
||||||
* @return a {@linkplain ClassDesc} describing the array type
|
* @return a {@linkplain ClassDesc} describing the array type
|
||||||
|
* @throws IllegalStateException if the resulting {@linkplain ClassDesc} would have an array rank of greater than 255
|
||||||
|
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||||
*/
|
*/
|
||||||
default ClassDesc arrayType() {
|
default ClassDesc arrayType() {
|
||||||
|
int depth = ConstantUtils.arrayDepth(descriptorString());
|
||||||
|
if (depth >= ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
|
||||||
|
throw new IllegalStateException(String.format("Cannot create an array type descriptor with more than %d dimensions",
|
||||||
|
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
|
||||||
|
}
|
||||||
return arrayType(1);
|
return arrayType(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,11 +163,14 @@ public interface ClassDesc
|
||||||
*
|
*
|
||||||
* @param rank the rank of the array
|
* @param rank the rank of the array
|
||||||
* @return a {@linkplain ClassDesc} describing the array type
|
* @return a {@linkplain ClassDesc} describing the array type
|
||||||
* @throws IllegalArgumentException if the rank is zero or negative
|
* @throws IllegalArgumentException if the rank is less than zero or if the rank of the resulting array type is
|
||||||
|
* greater than 255
|
||||||
|
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||||
*/
|
*/
|
||||||
default ClassDesc arrayType(int rank) {
|
default ClassDesc arrayType(int rank) {
|
||||||
if (rank <= 0)
|
int currentDepth = ConstantUtils.arrayDepth(descriptorString());
|
||||||
throw new IllegalArgumentException("rank: " + rank);
|
if (rank <= 0 || currentDepth + rank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)
|
||||||
|
throw new IllegalArgumentException("rank: " + currentDepth + rank);
|
||||||
return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
|
return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +178,12 @@ public interface ClassDesc
|
||||||
* Returns a {@linkplain ClassDesc} for a nested class of the class or
|
* Returns a {@linkplain ClassDesc} for a nested class of the class or
|
||||||
* interface type described by this {@linkplain ClassDesc}.
|
* interface type described by this {@linkplain ClassDesc}.
|
||||||
*
|
*
|
||||||
|
* @apiNote
|
||||||
|
*
|
||||||
|
* Example: If descriptor {@code d} describes the class {@code java.util.Map}, a
|
||||||
|
* descriptor for the class {@code java.util.Map.Entry} could be obtained
|
||||||
|
* by {@code d.nested("Entry")}.
|
||||||
|
*
|
||||||
* @param nestedName the unqualified name of the nested class
|
* @param nestedName the unqualified name of the nested class
|
||||||
* @return a {@linkplain ClassDesc} describing the nested class
|
* @return a {@linkplain ClassDesc} describing the nested class
|
||||||
* @throws NullPointerException if any argument is {@code null}
|
* @throws NullPointerException if any argument is {@code null}
|
||||||
|
|
|
@ -65,8 +65,9 @@ import java.util.Optional;
|
||||||
*/
|
*/
|
||||||
public interface Constable {
|
public interface Constable {
|
||||||
/**
|
/**
|
||||||
* Returns a nominal descriptor for this instance, if one can be
|
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||||
* constructed, or an empty {@link Optional} if one cannot be constructed.
|
* instance, if one can be constructed, or an empty {@link Optional}
|
||||||
|
* if one cannot be constructed.
|
||||||
*
|
*
|
||||||
* @return An {@link Optional} containing the resulting nominal descriptor,
|
* @return An {@link Optional} containing the resulting nominal descriptor,
|
||||||
* or an empty {@link Optional} if one cannot be constructed.
|
* or an empty {@link Optional} if one cannot be constructed.
|
||||||
|
|
|
@ -37,6 +37,7 @@ class ConstantUtils {
|
||||||
/** an empty constant descriptor */
|
/** an empty constant descriptor */
|
||||||
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
|
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
|
||||||
static final Constable[] EMPTY_CONSTABLE = new Constable[0];
|
static final Constable[] EMPTY_CONSTABLE = new Constable[0];
|
||||||
|
static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255;
|
||||||
|
|
||||||
private static final Set<String> pointyNames = Set.of("<init>", "<clinit>");
|
private static final Set<String> pointyNames = Set.of("<init>", "<clinit>");
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
* storing the value in a constant pool entry, or reconstituting the value given
|
* storing the value in a constant pool entry, or reconstituting the value given
|
||||||
* a class loading context. Every {@link java.lang.constant.ConstantDesc}
|
* a class loading context. Every {@link java.lang.constant.ConstantDesc}
|
||||||
* knows how to <em>resolve</em> itself -- compute the value that it describes --
|
* knows how to <em>resolve</em> itself -- compute the value that it describes --
|
||||||
* via {@link java.lang.constant.ConstantDesc#resolveConstantDesc(java.lang.invoke.MethodHandles.Lookup)}.
|
* via {@link java.lang.constant.ConstantDesc#resolveConstantDesc(java.lang.invoke.MethodHandles.Lookup) ConstantDesc.resolveConstantDesc}.
|
||||||
* This allows an API which accepts {@link java.lang.constant.ConstantDesc}
|
* This allows an API which accepts {@link java.lang.constant.ConstantDesc}
|
||||||
* objects to evaluate them reflectively, provided that the classes and methods
|
* objects to evaluate them reflectively, provided that the classes and methods
|
||||||
* referenced in their nominal description are present and accessible.
|
* referenced in their nominal description are present and accessible.
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
* When a bytecode-reading API encounters a constant pool entry, it can
|
* When a bytecode-reading API encounters a constant pool entry, it can
|
||||||
* convert it to the appropriate type of nominal descriptor. For dynamic
|
* convert it to the appropriate type of nominal descriptor. For dynamic
|
||||||
* constants, bytecode-reading APIs may wish to use the factory
|
* constants, bytecode-reading APIs may wish to use the factory
|
||||||
* {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[])},
|
* {@link java.lang.constant.DynamicConstantDesc#ofCanonical(DirectMethodHandleDesc, java.lang.String, ClassDesc, ConstantDesc[]) DynamicConstantDesc.ofCanonical},
|
||||||
* which will inspect the bootstrap and, for well-known bootstraps, return
|
* which will inspect the bootstrap and, for well-known bootstraps, return
|
||||||
* a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as
|
* a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as
|
||||||
* {@link java.lang.Enum.EnumDesc}.
|
* {@link java.lang.Enum.EnumDesc}.
|
||||||
|
|
|
@ -61,7 +61,8 @@ public interface TypeDescriptor {
|
||||||
boolean isArray();
|
boolean isArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this field descriptor describe a primitive type?
|
* Does this field descriptor describe a primitive type (including void.)
|
||||||
|
*
|
||||||
* @return whether this field descriptor describes a primitive type
|
* @return whether this field descriptor describes a primitive type
|
||||||
*/
|
*/
|
||||||
boolean isPrimitive();
|
boolean isPrimitive();
|
||||||
|
|
|
@ -1864,6 +1864,16 @@ public abstract class VarHandle implements Constable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare this {@linkplain VarHandle} with another object for equality.
|
||||||
|
* Two {@linkplain VarHandle}s are considered equal if they both describe the
|
||||||
|
* same instance field, both describe the same static field, both describe
|
||||||
|
* array elements for arrays with the same component type, or both describe
|
||||||
|
* the same component of an off-heap structure.
|
||||||
|
*
|
||||||
|
* @param o the other object
|
||||||
|
* @return Whether this {@linkplain VarHandle} is equal to the other object
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final boolean equals(Object o) {
|
public final boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -1883,6 +1893,12 @@ public abstract class VarHandle implements Constable {
|
||||||
|
|
||||||
abstract int internalHashCode();
|
abstract int internalHashCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a compact textual description of this {@linkplain VarHandle},
|
||||||
|
* including the type of variable described, and a description of its coordinates.
|
||||||
|
*
|
||||||
|
* @return A compact textual description of this {@linkplain VarHandle}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
return String.format("VarHandle[varType=%s, coord=%s]",
|
return String.format("VarHandle[varType=%s, coord=%s]",
|
||||||
|
@ -2272,6 +2288,14 @@ public abstract class VarHandle implements Constable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a compact textual description of this constant description.
|
||||||
|
* For a field {@linkplain VarHandle}, includes the owner, name, and type
|
||||||
|
* of the field, and whether it is static; for an array {@linkplain VarHandle},
|
||||||
|
* the name of the component type.
|
||||||
|
*
|
||||||
|
* @return A compact textual description of this descriptor
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
|
@ -244,6 +244,29 @@ public class ClassDescTest extends SymbolicDescTest {
|
||||||
testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any");
|
testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any");
|
||||||
testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any", "other");
|
testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any", "other");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClassDesc stringDesc = ClassDesc.ofDescriptor("Ljava/lang/String;");
|
||||||
|
ClassDesc stringArrDesc = stringDesc.arrayType(255);
|
||||||
|
try {
|
||||||
|
ClassDesc arrGreaterThan255 = stringArrDesc.arrayType();
|
||||||
|
fail("can't create an array type descriptor with more than 255 dimensions");
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
String descWith255ArrayDims = new String(new char[255]).replace('\0', '[');
|
||||||
|
try {
|
||||||
|
ClassDesc arrGreaterThan255 = ClassDesc.ofDescriptor(descWith255ArrayDims + "[Ljava/lang/String;");
|
||||||
|
fail("can't create an array type descriptor with more than 255 dimensions");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ClassDesc arrWith255Dims = ClassDesc.ofDescriptor(descWith255ArrayDims + "Ljava/lang/String;");
|
||||||
|
arrWith255Dims.arrayType(1);
|
||||||
|
fail("can't create an array type descriptor with more than 255 dimensions");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// good
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testBadNestedClasses(ClassDesc cr, String firstNestedName, String... moreNestedNames) {
|
private void testBadNestedClasses(ClassDesc cr, String firstNestedName, String... moreNestedNames) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue