--- a/src/java.base/share/classes/java/lang/Double.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/Double.java Thu Dec 13 10:35:09 2018 -0500
@@ -1077,8 +1077,8 @@
}
/**
- * 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
--- a/src/java.base/share/classes/java/lang/Float.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/Float.java Thu Dec 13 10:35:09 2018 -0500
@@ -989,8 +989,8 @@
}
/**
- * 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
--- a/src/java.base/share/classes/java/lang/Integer.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/Integer.java Thu Dec 13 10:35:09 2018 -0500
@@ -1838,8 +1838,8 @@
}
/**
- * 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
--- a/src/java.base/share/classes/java/lang/Long.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/Long.java Thu Dec 13 10:35:09 2018 -0500
@@ -1967,8 +1967,8 @@
}
/**
- * 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
--- a/src/java.base/share/classes/java/lang/String.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/String.java Thu Dec 13 10:35:09 2018 -0500
@@ -3545,8 +3545,8 @@
}
/**
- * 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
--- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java Thu Dec 13 10:35:09 2018 -0500
@@ -112,13 +112,13 @@
*
* 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 @@
* @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 @@
* 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 @@
*
* @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 @@
* 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}
--- a/src/java.base/share/classes/java/lang/constant/Constable.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/constant/Constable.java Thu Dec 13 10:35:09 2018 -0500
@@ -65,8 +65,9 @@
*/
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.
--- a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java Thu Dec 13 10:35:09 2018 -0500
@@ -37,6 +37,7 @@
/** 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>");
--- a/src/java.base/share/classes/java/lang/constant/package-info.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/constant/package-info.java Thu Dec 13 10:35:09 2018 -0500
@@ -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}.
--- a/src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/TypeDescriptor.java Thu Dec 13 10:35:09 2018 -0500
@@ -61,7 +61,8 @@
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();
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Dec 13 15:31:05 2018 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java Thu Dec 13 10:35:09 2018 -0500
@@ -1864,6 +1864,16 @@
}
}
+ /**
+ * 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 @@
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 @@
}
}
+ /**
+ * 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) {
--- a/test/jdk/java/lang/constant/ClassDescTest.java Thu Dec 13 15:31:05 2018 +0100
+++ b/test/jdk/java/lang/constant/ClassDescTest.java Thu Dec 13 10:35:09 2018 -0500
@@ -244,6 +244,29 @@
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) {