8215300: additional changes to constants API
Reviewed-by: goetz
This commit is contained in:
parent
a3df1d618e
commit
650f3fc113
src/java.base/share/classes/java/lang
test/jdk/java/lang/constant
@ -1077,8 +1077,8 @@ public final class Double extends Number
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, which is the instance
|
||||
* itself.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* instance, which is the instance itself.
|
||||
*
|
||||
* @return an {@link Optional} describing the {@linkplain Double} instance
|
||||
* @since 12
|
||||
|
@ -989,8 +989,8 @@ public final class Float extends Number
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, which is the instance
|
||||
* itself.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* instance, which is the instance itself.
|
||||
*
|
||||
* @return an {@link Optional} describing the {@linkplain Float} instance
|
||||
* @since 12
|
||||
|
@ -1838,8 +1838,8 @@ public final class Integer extends Number
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, which is the instance
|
||||
* itself.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* instance, which is the instance itself.
|
||||
*
|
||||
* @return an {@link Optional} describing the {@linkplain Integer} instance
|
||||
* @since 12
|
||||
|
@ -1967,8 +1967,8 @@ public final class Long extends Number
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, which is the instance
|
||||
* itself.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* instance, which is the instance itself.
|
||||
*
|
||||
* @return an {@link Optional} describing the {@linkplain Long} instance
|
||||
* @since 12
|
||||
|
@ -3545,8 +3545,8 @@ public final class String
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, which is the instance
|
||||
* itself.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* instance, which is the instance itself.
|
||||
*
|
||||
* @return an {@link Optional} describing the {@linkplain String} instance
|
||||
* @since 12
|
||||
|
@ -112,13 +112,13 @@ public interface ClassDesc
|
||||
*
|
||||
* A field type descriptor string for a non-array type is either
|
||||
* 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
|
||||
* by the fully qualified binary name of a class, followed by {@code ;}.
|
||||
* A field type descriptor for an array type is the character {@code [}
|
||||
* ({@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 ";"}.
|
||||
* A field type descriptor for an array type is the character {@code "["}
|
||||
* followed by the field descriptor for the component type. Examples of
|
||||
* valid type descriptor strings include {@code Ljava/lang/String;}, {@code I},
|
||||
* {@code [I}, {@code V}, {@code [Ljava/lang/String;}, etc.
|
||||
* for more detail.
|
||||
* valid type descriptor strings include {@code "Ljava/lang/String;"}, {@code "I"},
|
||||
* {@code "[I"}, {@code "V"}, {@code "[Ljava/lang/String;"}, etc.
|
||||
* See JVMS 4.3.2 ("Field Descriptors") for more detail.
|
||||
*
|
||||
* @param descriptor a field descriptor string
|
||||
* @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
|
||||
* correct format
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||
*/
|
||||
static ClassDesc ofDescriptor(String 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)
|
||||
? new PrimitiveClassDescImpl(descriptor)
|
||||
: new ReferenceClassDescImpl(descriptor);
|
||||
@ -139,8 +145,15 @@ public interface ClassDesc
|
||||
* is described by this {@linkplain ClassDesc}.
|
||||
*
|
||||
* @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() {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -150,11 +163,14 @@ public interface ClassDesc
|
||||
*
|
||||
* @param rank the rank of the array
|
||||
* @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) {
|
||||
if (rank <= 0)
|
||||
throw new IllegalArgumentException("rank: " + rank);
|
||||
int currentDepth = ConstantUtils.arrayDepth(descriptorString());
|
||||
if (rank <= 0 || currentDepth + rank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)
|
||||
throw new IllegalArgumentException("rank: " + currentDepth + rank);
|
||||
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
|
||||
* 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
|
||||
* @return a {@linkplain ClassDesc} describing the nested class
|
||||
* @throws NullPointerException if any argument is {@code null}
|
||||
|
@ -65,8 +65,9 @@ import java.util.Optional;
|
||||
*/
|
||||
public interface Constable {
|
||||
/**
|
||||
* Returns a nominal descriptor for this instance, if one can be
|
||||
* constructed, or an empty {@link Optional} if one cannot be constructed.
|
||||
* Returns an {@link Optional} containing the nominal descriptor for this
|
||||
* 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,
|
||||
* or an empty {@link Optional} if one cannot be constructed.
|
||||
|
@ -37,6 +37,7 @@ class ConstantUtils {
|
||||
/** an empty constant descriptor */
|
||||
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[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>");
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
* storing the value in a constant pool entry, or reconstituting the value given
|
||||
* a class loading context. Every {@link java.lang.constant.ConstantDesc}
|
||||
* 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}
|
||||
* objects to evaluate them reflectively, provided that the classes and methods
|
||||
* 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
|
||||
* convert it to the appropriate type of nominal descriptor. For dynamic
|
||||
* 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
|
||||
* a more specific subtype of {@link java.lang.constant.DynamicConstantDesc}, such as
|
||||
* {@link java.lang.Enum.EnumDesc}.
|
||||
|
@ -61,7 +61,8 @@ public interface TypeDescriptor {
|
||||
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
|
||||
*/
|
||||
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
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -1883,6 +1893,12 @@ public abstract class VarHandle implements Constable {
|
||||
|
||||
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
|
||||
public final String toString() {
|
||||
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
|
||||
public String toString() {
|
||||
switch (kind) {
|
||||
|
@ -244,6 +244,29 @@ public class ClassDescTest extends SymbolicDescTest {
|
||||
testBadNestedClasses(ClassDesc.ofDescriptor(p.descriptor), "any");
|
||||
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user