8338544: Dedicated Array class descriptor implementation
Reviewed-by: redestad, mchung, jvernee
This commit is contained in:
parent
158b93d19a
commit
25c2f48d45
@ -26,22 +26,13 @@ package java.lang.constant;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.TypeDescriptor;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.constant.ArrayClassDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.PrimitiveClassDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import sun.invoke.util.Wrapper;
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
|
||||
import static jdk.internal.constant.ConstantUtils.arrayDepth;
|
||||
import static jdk.internal.constant.ConstantUtils.binaryToInternal;
|
||||
import static jdk.internal.constant.ConstantUtils.concat;
|
||||
import static jdk.internal.constant.ConstantUtils.forPrimitiveType;
|
||||
import static jdk.internal.constant.ConstantUtils.internalToBinary;
|
||||
import static jdk.internal.constant.ConstantUtils.validateBinaryClassName;
|
||||
import static jdk.internal.constant.ConstantUtils.validateInternalClassName;
|
||||
import static jdk.internal.constant.ConstantUtils.validateMemberName;
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
@ -64,7 +55,8 @@ public sealed interface ClassDesc
|
||||
extends ConstantDesc,
|
||||
TypeDescriptor.OfField<ClassDesc>
|
||||
permits PrimitiveClassDescImpl,
|
||||
ReferenceClassDescImpl {
|
||||
ClassOrInterfaceDescImpl,
|
||||
ArrayClassDescImpl {
|
||||
|
||||
/**
|
||||
* Returns a {@linkplain ClassDesc} for a class or interface type,
|
||||
@ -84,7 +76,7 @@ public sealed interface ClassDesc
|
||||
*/
|
||||
static ClassDesc of(String name) {
|
||||
validateBinaryClassName(name);
|
||||
return ClassDesc.ofDescriptor(concat("L", binaryToInternal(name), ";"));
|
||||
return ConstantUtils.binaryNameToDesc(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +102,7 @@ public sealed interface ClassDesc
|
||||
*/
|
||||
static ClassDesc ofInternalName(String name) {
|
||||
validateInternalClassName(name);
|
||||
return ClassDesc.ofDescriptor(concat("L", name, ";"));
|
||||
return ConstantUtils.internalNameToDesc(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,11 +121,11 @@ public sealed interface ClassDesc
|
||||
*/
|
||||
static ClassDesc of(String packageName, String className) {
|
||||
validateBinaryClassName(packageName);
|
||||
if (packageName.isEmpty()) {
|
||||
return of(className);
|
||||
}
|
||||
validateMemberName(className, false);
|
||||
return ofDescriptor('L' + binaryToInternal(packageName) +
|
||||
if (packageName.isEmpty()) {
|
||||
return internalNameToDesc(className);
|
||||
}
|
||||
return ClassOrInterfaceDescImpl.ofValidated('L' + binaryToInternal(packageName) +
|
||||
'/' + className + ';');
|
||||
}
|
||||
|
||||
@ -168,7 +160,7 @@ public sealed interface ClassDesc
|
||||
return (descriptor.length() == 1)
|
||||
? forPrimitiveType(descriptor, 0)
|
||||
// will throw IAE on descriptor.length == 0 or if array dimensions too long
|
||||
: ReferenceClassDescImpl.of(descriptor);
|
||||
: parseReferenceTypeDesc(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,20 +172,7 @@ public sealed interface ClassDesc
|
||||
* ClassDesc} would have an array rank of greater than 255
|
||||
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||
*/
|
||||
default ClassDesc arrayType() {
|
||||
String desc = descriptorString();
|
||||
int depth = arrayDepth(desc);
|
||||
if (depth >= MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot create an array type descriptor with more than " +
|
||||
MAX_ARRAY_TYPE_DESC_DIMENSIONS + " dimensions");
|
||||
}
|
||||
String newDesc = "[".concat(desc);
|
||||
if (desc.length() == 1 && desc.charAt(0) == 'V') {
|
||||
throw new IllegalArgumentException("not a valid reference type descriptor: " + newDesc);
|
||||
}
|
||||
return ReferenceClassDescImpl.ofValidated(newDesc);
|
||||
}
|
||||
ClassDesc arrayType();
|
||||
|
||||
/**
|
||||
* Returns a {@linkplain ClassDesc} for an array type of the specified rank,
|
||||
@ -206,24 +185,7 @@ public sealed interface ClassDesc
|
||||
* 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 + " is not a positive value");
|
||||
}
|
||||
String desc = descriptorString();
|
||||
long currentDepth = arrayDepth(desc);
|
||||
long netRank = currentDepth + rank;
|
||||
if (netRank > MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
|
||||
throw new IllegalArgumentException("rank: " + netRank +
|
||||
" exceeds maximum supported dimension of " +
|
||||
MAX_ARRAY_TYPE_DESC_DIMENSIONS);
|
||||
}
|
||||
String newDesc = new StringBuilder(desc.length() + rank).repeat('[', rank).append(desc).toString();
|
||||
if (desc.length() == 1 && desc.charAt(0) == 'V') {
|
||||
throw new IllegalArgumentException("not a valid reference type descriptor: " + newDesc);
|
||||
}
|
||||
return ReferenceClassDescImpl.ofValidated(newDesc);
|
||||
}
|
||||
ClassDesc arrayType(int rank);
|
||||
|
||||
/**
|
||||
* Returns a {@linkplain ClassDesc} for a nested class of the class or
|
||||
@ -243,13 +205,7 @@ public sealed interface ClassDesc
|
||||
* @throws IllegalArgumentException if the nested class name is invalid
|
||||
*/
|
||||
default ClassDesc nested(String nestedName) {
|
||||
validateMemberName(nestedName, false);
|
||||
if (!isClassOrInterface())
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
String desc = descriptorString();
|
||||
StringBuilder sb = new StringBuilder(desc.length() + nestedName.length() + 1);
|
||||
sb.append(desc, 0, desc.length() - 1).append('$').append(nestedName).append(';');
|
||||
return ReferenceClassDescImpl.ofValidated(sb.toString());
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,16 +222,7 @@ public sealed interface ClassDesc
|
||||
* @throws IllegalArgumentException if the nested class name is invalid
|
||||
*/
|
||||
default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
|
||||
if (!isClassOrInterface())
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
validateMemberName(firstNestedName, false);
|
||||
// implicit null-check
|
||||
for (String addNestedNames : moreNestedNames) {
|
||||
validateMemberName(addNestedNames, false);
|
||||
}
|
||||
return moreNestedNames.length == 0
|
||||
? nested(firstNestedName)
|
||||
: nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", "")));
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,7 +231,7 @@ public sealed interface ClassDesc
|
||||
* @return whether this {@linkplain ClassDesc} describes an array type
|
||||
*/
|
||||
default boolean isArray() {
|
||||
return descriptorString().charAt(0) == '[';
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -293,7 +240,7 @@ public sealed interface ClassDesc
|
||||
* @return whether this {@linkplain ClassDesc} describes a primitive type
|
||||
*/
|
||||
default boolean isPrimitive() {
|
||||
return descriptorString().length() == 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,7 +249,7 @@ public sealed interface ClassDesc
|
||||
* @return whether this {@linkplain ClassDesc} describes a class or interface type
|
||||
*/
|
||||
default boolean isClassOrInterface() {
|
||||
return descriptorString().charAt(0) == 'L';
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,14 +260,6 @@ public sealed interface ClassDesc
|
||||
* if this descriptor does not describe an array type
|
||||
*/
|
||||
default ClassDesc componentType() {
|
||||
if (isArray()) {
|
||||
String desc = descriptorString();
|
||||
if (desc.length() == 2) {
|
||||
return Wrapper.forBasicType(desc.charAt(1)).basicClassDescriptor();
|
||||
} else {
|
||||
return ReferenceClassDescImpl.ofValidated(desc.substring(1));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -332,41 +271,17 @@ public sealed interface ClassDesc
|
||||
* default package, or this {@linkplain ClassDesc} does not describe a class or interface type
|
||||
*/
|
||||
default String packageName() {
|
||||
if (!isClassOrInterface())
|
||||
return "";
|
||||
String desc = descriptorString();
|
||||
int index = desc.lastIndexOf('/');
|
||||
return (index == -1) ? "" : internalToBinary(desc.substring(1, index));
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a human-readable name for the type described by this descriptor.
|
||||
*
|
||||
* @implSpec
|
||||
* <p>The default implementation returns the simple name
|
||||
* (e.g., {@code int}) for primitive types, the unqualified class name
|
||||
* for class or interface types, or the display name of the component type
|
||||
* suffixed with the appropriate number of {@code []} pairs for array types.
|
||||
*
|
||||
* @return the human-readable name
|
||||
* {@return a human-readable name for this {@code ClassDesc}}
|
||||
* For primitive types, this method returns the simple name (such as {@code int}).
|
||||
* For class or interface types, this method returns the unqualified class name.
|
||||
* For array types, this method returns the human-readable name of the component
|
||||
* type suffixed with the appropriate number of {@code []} pairs.
|
||||
*/
|
||||
default String displayName() {
|
||||
if (isPrimitive())
|
||||
return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
|
||||
else if (isClassOrInterface()) {
|
||||
String desc = descriptorString();
|
||||
return desc.substring(Math.max(1, desc.lastIndexOf('/') + 1), desc.length() - 1);
|
||||
}
|
||||
else if (isArray()) {
|
||||
int depth = arrayDepth(descriptorString());
|
||||
ClassDesc c = this;
|
||||
for (int i=0; i<depth; i++)
|
||||
c = c.componentType();
|
||||
return c.displayName().concat("[]".repeat(depth));
|
||||
}
|
||||
else
|
||||
throw new IllegalStateException(descriptorString());
|
||||
}
|
||||
String displayName();
|
||||
|
||||
/**
|
||||
* Returns a field type descriptor string for this type
|
||||
|
@ -24,9 +24,10 @@
|
||||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.PrimitiveClassDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
|
||||
import java.lang.Enum.EnumDesc;
|
||||
import java.lang.invoke.CallSite;
|
||||
@ -68,115 +69,120 @@ public final class ConstantDescs {
|
||||
// Don't change the order of these declarations!
|
||||
|
||||
/** {@link ClassDesc} representing {@link Object} */
|
||||
public static final ClassDesc CD_Object = ReferenceClassDescImpl.ofValidated("Ljava/lang/Object;");
|
||||
public static final ClassDesc CD_Object = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Object;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link String} */
|
||||
public static final ClassDesc CD_String = ReferenceClassDescImpl.ofValidated("Ljava/lang/String;");
|
||||
public static final ClassDesc CD_String = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/String;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Class} */
|
||||
public static final ClassDesc CD_Class = ReferenceClassDescImpl.ofValidated("Ljava/lang/Class;");
|
||||
public static final ClassDesc CD_Class = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Class;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Number} */
|
||||
public static final ClassDesc CD_Number = ReferenceClassDescImpl.ofValidated("Ljava/lang/Number;");
|
||||
public static final ClassDesc CD_Number = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Number;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Integer} */
|
||||
public static final ClassDesc CD_Integer = ReferenceClassDescImpl.ofValidated("Ljava/lang/Integer;");
|
||||
public static final ClassDesc CD_Integer = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Integer;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Long} */
|
||||
public static final ClassDesc CD_Long = ReferenceClassDescImpl.ofValidated("Ljava/lang/Long;");
|
||||
public static final ClassDesc CD_Long = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Long;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Float} */
|
||||
public static final ClassDesc CD_Float = ReferenceClassDescImpl.ofValidated("Ljava/lang/Float;");
|
||||
public static final ClassDesc CD_Float = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Float;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Double} */
|
||||
public static final ClassDesc CD_Double = ReferenceClassDescImpl.ofValidated("Ljava/lang/Double;");
|
||||
public static final ClassDesc CD_Double = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Double;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Short} */
|
||||
public static final ClassDesc CD_Short = ReferenceClassDescImpl.ofValidated("Ljava/lang/Short;");
|
||||
public static final ClassDesc CD_Short = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Short;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Byte} */
|
||||
public static final ClassDesc CD_Byte = ReferenceClassDescImpl.ofValidated("Ljava/lang/Byte;");
|
||||
public static final ClassDesc CD_Byte = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Byte;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Character} */
|
||||
public static final ClassDesc CD_Character = ReferenceClassDescImpl.ofValidated("Ljava/lang/Character;");
|
||||
public static final ClassDesc CD_Character = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Character;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Boolean} */
|
||||
public static final ClassDesc CD_Boolean = ReferenceClassDescImpl.ofValidated("Ljava/lang/Boolean;");
|
||||
public static final ClassDesc CD_Boolean = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Boolean;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Void} */
|
||||
public static final ClassDesc CD_Void = ReferenceClassDescImpl.ofValidated("Ljava/lang/Void;");
|
||||
public static final ClassDesc CD_Void = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Void;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Throwable} */
|
||||
public static final ClassDesc CD_Throwable = ReferenceClassDescImpl.ofValidated("Ljava/lang/Throwable;");
|
||||
public static final ClassDesc CD_Throwable = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Throwable;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Exception} */
|
||||
public static final ClassDesc CD_Exception = ReferenceClassDescImpl.ofValidated("Ljava/lang/Exception;");
|
||||
public static final ClassDesc CD_Exception = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Exception;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Enum} */
|
||||
public static final ClassDesc CD_Enum = ReferenceClassDescImpl.ofValidated("Ljava/lang/Enum;");
|
||||
public static final ClassDesc CD_Enum = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Enum;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link VarHandle} */
|
||||
public static final ClassDesc CD_VarHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/VarHandle;");
|
||||
public static final ClassDesc CD_VarHandle = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/VarHandle;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandles} */
|
||||
public static final ClassDesc CD_MethodHandles = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles;");
|
||||
public static final ClassDesc CD_MethodHandles = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandles.Lookup} */
|
||||
public static final ClassDesc CD_MethodHandles_Lookup = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles$Lookup;");
|
||||
public static final ClassDesc CD_MethodHandles_Lookup = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles$Lookup;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandle} */
|
||||
public static final ClassDesc CD_MethodHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandle;");
|
||||
public static final ClassDesc CD_MethodHandle = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandle;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodType} */
|
||||
public static final ClassDesc CD_MethodType = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodType;");
|
||||
public static final ClassDesc CD_MethodType = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodType;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link CallSite} */
|
||||
public static final ClassDesc CD_CallSite = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/CallSite;");
|
||||
public static final ClassDesc CD_CallSite = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/CallSite;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Collection} */
|
||||
public static final ClassDesc CD_Collection = ReferenceClassDescImpl.ofValidated("Ljava/util/Collection;");
|
||||
public static final ClassDesc CD_Collection = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/Collection;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link List} */
|
||||
public static final ClassDesc CD_List = ReferenceClassDescImpl.ofValidated("Ljava/util/List;");
|
||||
public static final ClassDesc CD_List = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/List;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Set} */
|
||||
public static final ClassDesc CD_Set = ReferenceClassDescImpl.ofValidated("Ljava/util/Set;");
|
||||
public static final ClassDesc CD_Set = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/Set;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Map} */
|
||||
public static final ClassDesc CD_Map = ReferenceClassDescImpl.ofValidated("Ljava/util/Map;");
|
||||
public static final ClassDesc CD_Map = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/Map;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ConstantDesc} */
|
||||
public static final ClassDesc CD_ConstantDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/ConstantDesc;");
|
||||
public static final ClassDesc CD_ConstantDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/ConstantDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ClassDesc} */
|
||||
public static final ClassDesc CD_ClassDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/ClassDesc;");
|
||||
public static final ClassDesc CD_ClassDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/ClassDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link EnumDesc} */
|
||||
public static final ClassDesc CD_EnumDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/Enum$EnumDesc;");
|
||||
public static final ClassDesc CD_EnumDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Enum$EnumDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodTypeDesc} */
|
||||
public static final ClassDesc CD_MethodTypeDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/MethodTypeDesc;");
|
||||
public static final ClassDesc CD_MethodTypeDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/MethodTypeDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandleDesc} */
|
||||
public static final ClassDesc CD_MethodHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/MethodHandleDesc;");
|
||||
public static final ClassDesc CD_MethodHandleDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/MethodHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DirectMethodHandleDesc} */
|
||||
public static final ClassDesc CD_DirectMethodHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc;");
|
||||
public static final ClassDesc CD_DirectMethodHandleDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link VarHandleDesc} */
|
||||
public static final ClassDesc CD_VarHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/VarHandle$VarHandleDesc;");
|
||||
public static final ClassDesc CD_VarHandleDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/VarHandle$VarHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
|
||||
public static final ClassDesc CD_MethodHandleDesc_Kind = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc$Kind;");
|
||||
public static final ClassDesc CD_MethodHandleDesc_Kind = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc$Kind;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DynamicConstantDesc} */
|
||||
public static final ClassDesc CD_DynamicConstantDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DynamicConstantDesc;");
|
||||
public static final ClassDesc CD_DynamicConstantDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/DynamicConstantDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DynamicCallSiteDesc} */
|
||||
public static final ClassDesc CD_DynamicCallSiteDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DynamicCallSiteDesc;");
|
||||
public static final ClassDesc CD_DynamicCallSiteDesc = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/constant/DynamicCallSiteDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ConstantBootstraps} */
|
||||
public static final ClassDesc CD_ConstantBootstraps = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/ConstantBootstraps;");
|
||||
public static final ClassDesc CD_ConstantBootstraps = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/ConstantBootstraps;");
|
||||
|
||||
static {
|
||||
// avoid circular initialization
|
||||
ConstantUtils.CD_Object_array = CD_Object.arrayType();
|
||||
}
|
||||
|
||||
private static final ClassDesc[] INDY_BOOTSTRAP_ARGS = {
|
||||
CD_MethodHandles_Lookup,
|
||||
@ -229,7 +235,7 @@ public final class ConstantDescs {
|
||||
/** {@link MethodHandleDesc} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...) ConstantBootstraps.invoke} */
|
||||
public static final DirectMethodHandleDesc BSM_INVOKE
|
||||
= ofConstantBootstrap(CD_ConstantBootstraps, "invoke",
|
||||
CD_Object, CD_MethodHandle, CD_Object.arrayType());
|
||||
CD_Object, CD_MethodHandle, ConstantUtils.CD_Object_array);
|
||||
|
||||
/**
|
||||
* {@link MethodHandleDesc} representing {@link ConstantBootstraps#explicitCast(Lookup, String, Class, Object) ConstantBootstraps.explicitCast}
|
||||
|
@ -42,8 +42,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.invoke.util.BytecodeName;
|
||||
@ -65,8 +66,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
/*non-public*/
|
||||
abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesData> {
|
||||
|
||||
private static final ClassDesc CD_LambdaForm = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;");
|
||||
private static final ClassDesc CD_BoundMethodHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/BoundMethodHandle;");
|
||||
private static final ClassDesc CD_LambdaForm = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;");
|
||||
private static final ClassDesc CD_BoundMethodHandle = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/BoundMethodHandle;");
|
||||
|
||||
private final Class<T> topClass;
|
||||
private final Class<K> keyType;
|
||||
@ -974,7 +975,7 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
||||
: cls == MethodType.class ? CD_MethodType
|
||||
: cls == LambdaForm.class ? CD_LambdaForm
|
||||
: cls == BoundMethodHandle.class ? CD_BoundMethodHandle
|
||||
: ReferenceClassDescImpl.ofValidated(cls.descriptorString());
|
||||
: ConstantUtils.referenceClassDesc(cls.descriptorString());
|
||||
}
|
||||
|
||||
static MethodTypeDesc methodDesc(MethodType mt) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.misc.CDS;
|
||||
import jdk.internal.util.ClassFileDumper;
|
||||
import sun.invoke.util.VerifyAccess;
|
||||
@ -53,10 +54,8 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.STRONG_LOADER_LINK;
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
@ -157,7 +156,7 @@ import sun.invoke.util.Wrapper;
|
||||
implMethodDesc = methodDesc(implInfo.getMethodType());
|
||||
constructorType = factoryType.changeReturnType(Void.TYPE);
|
||||
lambdaClassName = lambdaClassName(targetClass);
|
||||
lambdaClassEntry = pool.classEntry(ReferenceClassDescImpl.ofValidated(ConstantUtils.concat("L", lambdaClassName, ";")));
|
||||
lambdaClassEntry = pool.classEntry(ConstantUtils.internalNameToDesc(lambdaClassName));
|
||||
// If the target class invokes a protected method inherited from a
|
||||
// superclass in a different package, or does 'invokespecial', the
|
||||
// lambda class has no access to the resolved method, or does
|
||||
@ -407,9 +406,9 @@ import sun.invoke.util.Wrapper;
|
||||
|
||||
private static class SerializationSupport {
|
||||
// Serialization support
|
||||
private static final ClassDesc CD_SerializedLambda = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/SerializedLambda;");
|
||||
private static final ClassDesc CD_ObjectOutputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectOutputStream;");
|
||||
private static final ClassDesc CD_ObjectInputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectInputStream;");
|
||||
private static final ClassDesc CD_SerializedLambda = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/SerializedLambda;");
|
||||
private static final ClassDesc CD_ObjectOutputStream = ClassOrInterfaceDescImpl.ofValidated("Ljava/io/ObjectOutputStream;");
|
||||
private static final ClassDesc CD_ObjectInputStream = ClassOrInterfaceDescImpl.ofValidated("Ljava/io/ObjectInputStream;");
|
||||
private static final MethodTypeDesc MTD_Object = MethodTypeDescImpl.ofValidated(CD_Object);
|
||||
private static final MethodTypeDesc MTD_void_ObjectOutputStream = MethodTypeDescImpl.ofValidated(CD_void, CD_ObjectOutputStream);
|
||||
private static final MethodTypeDesc MTD_void_ObjectInputStream = MethodTypeDescImpl.ofValidated(CD_void, CD_ObjectInputStream);
|
||||
@ -418,10 +417,10 @@ import sun.invoke.util.Wrapper;
|
||||
private static final String NAME_METHOD_READ_OBJECT = "readObject";
|
||||
private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
|
||||
|
||||
static final ClassDesc CD_NotSerializableException = ReferenceClassDescImpl.ofValidated("Ljava/io/NotSerializableException;");
|
||||
static final ClassDesc CD_NotSerializableException = ClassOrInterfaceDescImpl.ofValidated("Ljava/io/NotSerializableException;");
|
||||
static final MethodTypeDesc MTD_CTOR_NOT_SERIALIZABLE_EXCEPTION = MethodTypeDescImpl.ofValidated(CD_void, CD_String);
|
||||
static final MethodTypeDesc MTD_CTOR_SERIALIZED_LAMBDA = MethodTypeDescImpl.ofValidated(CD_void,
|
||||
CD_Class, CD_String, CD_String, CD_String, CD_int, CD_String, CD_String, CD_String, CD_String, ReferenceClassDescImpl.ofValidated("[Ljava/lang/Object;"));
|
||||
CD_Class, CD_String, CD_String, CD_String, CD_int, CD_String, CD_String, CD_String, CD_String, ConstantUtils.CD_Object_array);
|
||||
|
||||
}
|
||||
|
||||
@ -557,12 +556,12 @@ import sun.invoke.util.Wrapper;
|
||||
}
|
||||
|
||||
static ClassDesc implClassDesc(Class<?> cls) {
|
||||
return cls.isHidden() ? null : ReferenceClassDescImpl.ofValidated(cls.descriptorString());
|
||||
return cls.isHidden() ? null : ConstantUtils.referenceClassDesc(cls.descriptorString());
|
||||
}
|
||||
|
||||
static ClassDesc classDesc(Class<?> cls) {
|
||||
return cls.isPrimitive() ? Wrapper.forPrimitiveType(cls).basicClassDescriptor()
|
||||
: ReferenceClassDescImpl.ofValidated(cls.descriptorString());
|
||||
: ConstantUtils.referenceClassDesc(cls.descriptorString());
|
||||
}
|
||||
|
||||
static MethodTypeDesc methodDesc(MethodType mt) {
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import sun.invoke.util.VerifyAccess;
|
||||
import sun.invoke.util.VerifyType;
|
||||
import sun.invoke.util.Wrapper;
|
||||
@ -50,7 +52,6 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
@ -59,7 +60,6 @@ import static java.lang.invoke.LambdaForm.BasicType.*;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
import static jdk.internal.constant.ConstantUtils.concat;
|
||||
import static jdk.internal.constant.ConstantUtils.validateInternalClassName;
|
||||
|
||||
/**
|
||||
@ -69,16 +69,16 @@ import static jdk.internal.constant.ConstantUtils.validateInternalClassName;
|
||||
*/
|
||||
class InvokerBytecodeGenerator {
|
||||
/** Define class names for convenience. */
|
||||
private static final ClassDesc CD_CasesHolder = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl$CasesHolder;");
|
||||
private static final ClassDesc CD_DirectMethodHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/DirectMethodHandle;");
|
||||
private static final ClassDesc CD_MemberName = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MemberName;");
|
||||
private static final ClassDesc CD_MethodHandleImpl = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl;");
|
||||
private static final ClassDesc CD_LambdaForm = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;");
|
||||
private static final ClassDesc CD_LambdaForm_Name = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm$Name;");
|
||||
private static final ClassDesc CD_LoopClauses = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl$LoopClauses;");
|
||||
private static final ClassDesc CD_Object_array = ReferenceClassDescImpl.ofValidated("[Ljava/lang/Object;");
|
||||
private static final ClassDesc CD_MethodHandle_array = ReferenceClassDescImpl.ofValidated("[Ljava/lang/invoke/MethodHandle;");
|
||||
private static final ClassDesc CD_MethodHandle_array2 = ReferenceClassDescImpl.ofValidated("[[Ljava/lang/invoke/MethodHandle;");
|
||||
private static final ClassDesc CD_CasesHolder = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl$CasesHolder;");
|
||||
private static final ClassDesc CD_DirectMethodHandle = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/DirectMethodHandle;");
|
||||
private static final ClassDesc CD_MemberName = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MemberName;");
|
||||
private static final ClassDesc CD_MethodHandleImpl = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl;");
|
||||
private static final ClassDesc CD_LambdaForm = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;");
|
||||
private static final ClassDesc CD_LambdaForm_Name = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm$Name;");
|
||||
private static final ClassDesc CD_LoopClauses = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/MethodHandleImpl$LoopClauses;");
|
||||
private static final ClassDesc CD_Object_array = ConstantUtils.CD_Object_array;
|
||||
private static final ClassDesc CD_MethodHandle_array = CD_MethodHandle.arrayType();
|
||||
private static final ClassDesc CD_MethodHandle_array2 = CD_MethodHandle_array.arrayType();
|
||||
|
||||
private static final MethodTypeDesc MTD_boolean_Object = MethodTypeDescImpl.ofValidated(CD_boolean, CD_Object);
|
||||
private static final MethodTypeDesc MTD_Object_int = MethodTypeDescImpl.ofValidated(CD_Object, CD_int);
|
||||
@ -133,7 +133,7 @@ class InvokerBytecodeGenerator {
|
||||
this.name = name;
|
||||
this.className = CLASS_PREFIX.concat(name);
|
||||
validateInternalClassName(name);
|
||||
this.classEntry = pool.classEntry(ReferenceClassDescImpl.ofValidated(concat("L", className, ";")));
|
||||
this.classEntry = pool.classEntry(ConstantUtils.internalNameToDesc(className));
|
||||
this.lambdaForm = lambdaForm;
|
||||
this.invokerName = invokerName;
|
||||
this.invokerType = invokerType;
|
||||
@ -517,11 +517,11 @@ class InvokerBytecodeGenerator {
|
||||
return true;
|
||||
}
|
||||
|
||||
static final Annotation DONTINLINE = Annotation.of(ReferenceClassDescImpl.ofValidated("Ljdk/internal/vm/annotation/DontInline;"));
|
||||
static final Annotation FORCEINLINE = Annotation.of(ReferenceClassDescImpl.ofValidated("Ljdk/internal/vm/annotation/ForceInline;"));
|
||||
static final Annotation HIDDEN = Annotation.of(ReferenceClassDescImpl.ofValidated("Ljdk/internal/vm/annotation/Hidden;"));
|
||||
static final Annotation INJECTEDPROFILE = Annotation.of(ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/InjectedProfile;"));
|
||||
static final Annotation LF_COMPILED = Annotation.of(ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm$Compiled;"));
|
||||
static final Annotation DONTINLINE = Annotation.of(ClassOrInterfaceDescImpl.ofValidated("Ljdk/internal/vm/annotation/DontInline;"));
|
||||
static final Annotation FORCEINLINE = Annotation.of(ClassOrInterfaceDescImpl.ofValidated("Ljdk/internal/vm/annotation/ForceInline;"));
|
||||
static final Annotation HIDDEN = Annotation.of(ClassOrInterfaceDescImpl.ofValidated("Ljdk/internal/vm/annotation/Hidden;"));
|
||||
static final Annotation INJECTEDPROFILE = Annotation.of(ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/InjectedProfile;"));
|
||||
static final Annotation LF_COMPILED = Annotation.of(ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm$Compiled;"));
|
||||
|
||||
// Suppress method in backtraces displayed to the user, mark this method as
|
||||
// a compiled LambdaForm, then either force or prohibit inlining.
|
||||
@ -1649,7 +1649,7 @@ class InvokerBytecodeGenerator {
|
||||
: cls == MemberName.class ? CD_MemberName
|
||||
: cls == MethodType.class ? CD_MethodType
|
||||
: cls.isPrimitive() ? Wrapper.forPrimitiveType(cls).basicClassDescriptor()
|
||||
: ReferenceClassDescImpl.ofValidated(cls.descriptorString());
|
||||
: ConstantUtils.referenceClassDesc(cls.descriptorString());
|
||||
}
|
||||
|
||||
static MethodTypeDesc methodDesc(MethodType mt) {
|
||||
|
@ -27,8 +27,9 @@ package java.lang.invoke;
|
||||
|
||||
import jdk.internal.access.JavaLangInvokeAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.foreign.abi.NativeEntryPoint;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
@ -54,7 +55,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
@ -67,7 +67,6 @@ import static java.lang.invoke.MethodHandleNatives.Constants.MN_HIDDEN_MEMBER;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
||||
|
||||
/**
|
||||
* Trusted implementation code for MethodHandle.
|
||||
@ -1038,7 +1037,7 @@ abstract class MethodHandleImpl {
|
||||
// That way we can lazily load the code and set up the constants.
|
||||
private static class BindCaller {
|
||||
|
||||
private static final ClassDesc CD_Object_array = ReferenceClassDescImpl.ofValidated("[Ljava/lang/Object;");
|
||||
private static final ClassDesc CD_Object_array = ConstantUtils.CD_Object_array;
|
||||
private static final MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
|
||||
private static final MethodType REFLECT_INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object.class, Object[].class);
|
||||
|
||||
@ -1267,7 +1266,7 @@ abstract class MethodHandleImpl {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return ClassFile.of().build(ReferenceClassDescImpl.ofValidated("LInjectedInvoker;"), clb -> clb
|
||||
return ClassFile.of().build(ClassOrInterfaceDescImpl.ofValidated("LInjectedInvoker;"), clb -> clb
|
||||
.withFlags(ACC_PRIVATE | ACC_SUPER)
|
||||
.withMethodBody(
|
||||
"invoke_V",
|
||||
|
@ -28,9 +28,9 @@ package java.lang.invoke;
|
||||
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.util.ClassFileDumper;
|
||||
import jdk.internal.util.ReferenceKey;
|
||||
@ -1088,10 +1088,10 @@ public final class StringConcatFactory {
|
||||
static final MethodHandles.Lookup STR_LOOKUP = new MethodHandles.Lookup(String.class);
|
||||
|
||||
static final ClassDesc CD_CONCAT = ConstantUtils.binaryNameToDesc(CLASS_NAME);
|
||||
static final ClassDesc CD_StringConcatHelper = ReferenceClassDescImpl.ofValidated("Ljava/lang/StringConcatHelper;");
|
||||
static final ClassDesc CD_StringConcatBase = ReferenceClassDescImpl.ofValidated("Ljava/lang/StringConcatHelper$StringConcatBase;");
|
||||
static final ClassDesc CD_Array_byte = ReferenceClassDescImpl.ofValidated("[B");
|
||||
static final ClassDesc CD_Array_String = ReferenceClassDescImpl.ofValidated("[Ljava/lang/String;");
|
||||
static final ClassDesc CD_StringConcatHelper = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/StringConcatHelper;");
|
||||
static final ClassDesc CD_StringConcatBase = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/StringConcatHelper$StringConcatBase;");
|
||||
static final ClassDesc CD_Array_byte = CD_byte.arrayType();
|
||||
static final ClassDesc CD_Array_String = CD_String.arrayType();
|
||||
|
||||
static final MethodTypeDesc MTD_byte_char = MethodTypeDescImpl.ofValidated(CD_byte, CD_char);
|
||||
static final MethodTypeDesc MTD_byte = MethodTypeDescImpl.ofValidated(CD_byte);
|
||||
|
@ -30,8 +30,9 @@ import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.TypeKind;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.lang.classfile.constantpool.MethodRefEntry;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
@ -202,6 +203,6 @@ class TypeConvertingMethodAdapter {
|
||||
return cls.isPrimitive() ? Wrapper.forPrimitiveType(cls).basicClassDescriptor()
|
||||
: cls == Object.class ? CD_Object
|
||||
: cls == String.class ? CD_String
|
||||
: ReferenceClassDescImpl.ofValidated(cls.descriptorString());
|
||||
: ConstantUtils.referenceClassDesc(cls.descriptorString());
|
||||
}
|
||||
}
|
||||
|
@ -39,9 +39,10 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
@ -64,18 +65,18 @@ final class ProxyGenerator {
|
||||
ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS);
|
||||
|
||||
private static final ClassDesc
|
||||
CD_ClassLoader = ReferenceClassDescImpl.ofValidated("Ljava/lang/ClassLoader;"),
|
||||
CD_Class_array = ReferenceClassDescImpl.ofValidated("[Ljava/lang/Class;"),
|
||||
CD_ClassNotFoundException = ReferenceClassDescImpl.ofValidated("Ljava/lang/ClassNotFoundException;"),
|
||||
CD_NoClassDefFoundError = ReferenceClassDescImpl.ofValidated("Ljava/lang/NoClassDefFoundError;"),
|
||||
CD_IllegalAccessException = ReferenceClassDescImpl.ofValidated("Ljava/lang/IllegalAccessException;"),
|
||||
CD_InvocationHandler = ReferenceClassDescImpl.ofValidated("Ljava/lang/reflect/InvocationHandler;"),
|
||||
CD_Method = ReferenceClassDescImpl.ofValidated("Ljava/lang/reflect/Method;"),
|
||||
CD_NoSuchMethodError = ReferenceClassDescImpl.ofValidated("Ljava/lang/NoSuchMethodError;"),
|
||||
CD_NoSuchMethodException = ReferenceClassDescImpl.ofValidated("Ljava/lang/NoSuchMethodException;"),
|
||||
CD_Object_array = ReferenceClassDescImpl.ofValidated("[Ljava/lang/Object;"),
|
||||
CD_Proxy = ReferenceClassDescImpl.ofValidated("Ljava/lang/reflect/Proxy;"),
|
||||
CD_UndeclaredThrowableException = ReferenceClassDescImpl.ofValidated("Ljava/lang/reflect/UndeclaredThrowableException;");
|
||||
CD_ClassLoader = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/ClassLoader;"),
|
||||
CD_Class_array = CD_Class.arrayType(),
|
||||
CD_ClassNotFoundException = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/ClassNotFoundException;"),
|
||||
CD_NoClassDefFoundError = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/NoClassDefFoundError;"),
|
||||
CD_IllegalAccessException = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/IllegalAccessException;"),
|
||||
CD_InvocationHandler = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/reflect/InvocationHandler;"),
|
||||
CD_Method = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/reflect/Method;"),
|
||||
CD_NoSuchMethodError = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/NoSuchMethodError;"),
|
||||
CD_NoSuchMethodException = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/NoSuchMethodException;"),
|
||||
CD_Object_array = ConstantUtils.CD_Object_array,
|
||||
CD_Proxy = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/reflect/Proxy;"),
|
||||
CD_UndeclaredThrowableException = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/reflect/UndeclaredThrowableException;");
|
||||
|
||||
private static final MethodTypeDesc
|
||||
MTD_boolean = MethodTypeDescImpl.ofValidated(CD_boolean),
|
||||
|
@ -48,9 +48,9 @@ import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.instruction.SwitchCase;
|
||||
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.misc.PreviewFeatures;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
@ -82,8 +82,8 @@ public class SwitchBootstraps {
|
||||
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||
private static final boolean previewEnabled = PreviewFeatures.isEnabled();
|
||||
|
||||
private static final ClassDesc CD_BiPredicate = ReferenceClassDescImpl.ofValidated("Ljava/util/function/BiPredicate;");
|
||||
private static final ClassDesc CD_Objects = ReferenceClassDescImpl.ofValidated("Ljava/util/Objects;");
|
||||
private static final ClassDesc CD_BiPredicate = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/function/BiPredicate;");
|
||||
private static final ClassDesc CD_Objects = ClassOrInterfaceDescImpl.ofValidated("Ljava/util/Objects;");
|
||||
|
||||
private static final MethodTypeDesc CHECK_INDEX_DESCRIPTOR =
|
||||
MethodTypeDescImpl.ofValidated(CD_int, CD_int, CD_int);
|
||||
@ -584,7 +584,7 @@ public class SwitchBootstraps {
|
||||
|
||||
TypePairs typePair = TypePairs.of(Wrapper.asPrimitiveType(selectorType), classLabel);
|
||||
String methodName = TypePairs.typePairToName.get(typePair);
|
||||
cb.invokestatic(referenceClassDesc(ExactConversionsSupport.class),
|
||||
cb.invokestatic(ConstantUtils.referenceClassDesc(ExactConversionsSupport.class),
|
||||
methodName,
|
||||
MethodTypeDesc.of(CD_boolean, classDesc(typePair.from)))
|
||||
.ifeq(next);
|
||||
|
@ -34,8 +34,6 @@ import java.lang.constant.MethodTypeDesc;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
|
||||
import static java.lang.classfile.constantpool.PoolEntry.*;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
|
@ -43,11 +43,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.constant.PrimitiveClassDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.util.Preconditions;
|
||||
|
||||
import static java.lang.classfile.ClassFile.ACC_STATIC;
|
||||
import static java.lang.classfile.ClassFile.*;
|
||||
import static java.lang.classfile.constantpool.PoolEntry.*;
|
||||
import static java.lang.constant.ConstantDescs.*;
|
||||
import static jdk.internal.classfile.impl.RawBytecodeHelper.*;
|
||||
@ -1059,7 +1058,7 @@ public final class StackMapGenerator {
|
||||
if (desc == CD_double) return pushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||
return desc == CD_void ? this
|
||||
: pushStack(
|
||||
desc instanceof PrimitiveClassDescImpl
|
||||
desc.isPrimitive()
|
||||
? (desc == CD_float ? Type.FLOAT_TYPE : Type.INTEGER_TYPE)
|
||||
: Type.referenceType(desc));
|
||||
}
|
||||
@ -1069,7 +1068,7 @@ public final class StackMapGenerator {
|
||||
if (desc == CD_double) return decStack1PushStack(Type.DOUBLE_TYPE, Type.DOUBLE2_TYPE);
|
||||
return desc == CD_void ? this
|
||||
: decStack1PushStack(
|
||||
desc instanceof PrimitiveClassDescImpl
|
||||
desc.isPrimitive()
|
||||
? (desc == CD_float ? Type.FLOAT_TYPE : Type.INTEGER_TYPE)
|
||||
: Type.referenceType(desc));
|
||||
}
|
||||
@ -1274,7 +1273,7 @@ public final class StackMapGenerator {
|
||||
locals[localsSize + 1] = Type.DOUBLE2_TYPE;
|
||||
localsSize += 2;
|
||||
} else {
|
||||
if (desc instanceof ReferenceClassDescImpl) {
|
||||
if (!desc.isPrimitive()) {
|
||||
type = Type.referenceType(desc);
|
||||
} else if (desc == CD_float) {
|
||||
type = Type.FLOAT_TYPE;
|
||||
@ -1459,14 +1458,14 @@ public final class StackMapGenerator {
|
||||
//frequently used types to reduce footprint
|
||||
static final Type OBJECT_TYPE = referenceType(CD_Object),
|
||||
THROWABLE_TYPE = referenceType(CD_Throwable),
|
||||
INT_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[I")),
|
||||
BOOLEAN_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[Z")),
|
||||
BYTE_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[B")),
|
||||
CHAR_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[C")),
|
||||
SHORT_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[S")),
|
||||
LONG_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[J")),
|
||||
DOUBLE_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[D")),
|
||||
FLOAT_ARRAY_TYPE = referenceType(ReferenceClassDescImpl.ofValidated("[F")),
|
||||
INT_ARRAY_TYPE = referenceType(CD_int.arrayType()),
|
||||
BOOLEAN_ARRAY_TYPE = referenceType(CD_boolean.arrayType()),
|
||||
BYTE_ARRAY_TYPE = referenceType(CD_byte.arrayType()),
|
||||
CHAR_ARRAY_TYPE = referenceType(CD_char.arrayType()),
|
||||
SHORT_ARRAY_TYPE = referenceType(CD_short.arrayType()),
|
||||
LONG_ARRAY_TYPE = referenceType(CD_long.arrayType()),
|
||||
DOUBLE_ARRAY_TYPE = referenceType(CD_double.arrayType()),
|
||||
FLOAT_ARRAY_TYPE = referenceType(CD_float.arrayType()),
|
||||
STRING_TYPE = referenceType(CD_String),
|
||||
CLASS_TYPE = referenceType(CD_Class),
|
||||
METHOD_HANDLE_TYPE = referenceType(CD_MethodHandle),
|
||||
@ -1531,8 +1530,8 @@ public final class StackMapGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ClassDesc CD_Cloneable = ReferenceClassDescImpl.ofValidated("Ljava/lang/Cloneable;");
|
||||
private static final ClassDesc CD_Serializable = ReferenceClassDescImpl.ofValidated("Ljava/io/Serializable;");
|
||||
private static final ClassDesc CD_Cloneable = ClassOrInterfaceDescImpl.ofValidated("Ljava/lang/Cloneable;");
|
||||
private static final ClassDesc CD_Serializable = ClassOrInterfaceDescImpl.ofValidated("Ljava/io/Serializable;");
|
||||
|
||||
private Type mergeReferenceFrom(Type from, ClassHierarchyImpl context) {
|
||||
if (from == NULL_TYPE) {
|
||||
|
@ -42,7 +42,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import jdk.internal.constant.ClassOrInterfaceDescImpl;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
@ -134,8 +134,8 @@ public class Util {
|
||||
}
|
||||
|
||||
public static String toInternalName(ClassDesc cd) {
|
||||
if (cd instanceof ReferenceClassDescImpl rcd) {
|
||||
return rcd.internalName();
|
||||
if (cd instanceof ClassOrInterfaceDescImpl coi) {
|
||||
return coi.internalName();
|
||||
}
|
||||
throw new IllegalArgumentException(cd.descriptorString());
|
||||
}
|
||||
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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.constant;
|
||||
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_void;
|
||||
import static jdk.internal.constant.ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS;
|
||||
|
||||
/**
|
||||
* An array class descriptor.
|
||||
* Restrictions: <ul>
|
||||
* <li>{@code rank} must be in {@code [1, 255]}
|
||||
* <li>{@code element} must not be void or array
|
||||
* </ul>
|
||||
*/
|
||||
public final class ArrayClassDescImpl implements ClassDesc {
|
||||
private final ClassDesc elementType;
|
||||
private final int rank;
|
||||
private @Stable String cachedDescriptorString;
|
||||
|
||||
public static ArrayClassDescImpl ofValidatedDescriptor(String desc) {
|
||||
assert desc.charAt(0) == '[';
|
||||
var lastChar = desc.charAt(desc.length() - 1);
|
||||
ArrayClassDescImpl ret;
|
||||
if (lastChar != ';') {
|
||||
// Primitive element arrays
|
||||
ret = ofValidated(Wrapper.forBasicType(lastChar).basicClassDescriptor(), desc.length() - 1);
|
||||
} else {
|
||||
int level = ConstantUtils.arrayDepth(desc, 0);
|
||||
ret = ofValidated(ClassOrInterfaceDescImpl.ofValidated(desc.substring(level)), level);
|
||||
}
|
||||
ret.cachedDescriptorString = desc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static ArrayClassDescImpl ofValidated(ClassDesc elementType, int rank) {
|
||||
assert !elementType.isArray() && elementType != CD_void;
|
||||
assert rank > 0 && rank <= MAX_ARRAY_TYPE_DESC_DIMENSIONS;
|
||||
|
||||
return new ArrayClassDescImpl(elementType, rank);
|
||||
}
|
||||
|
||||
private ArrayClassDescImpl(ClassDesc elementType, int rank) {
|
||||
this.elementType = elementType;
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType() {
|
||||
int rank = this.rank + 1;
|
||||
if (rank > MAX_ARRAY_TYPE_DESC_DIMENSIONS)
|
||||
throw new IllegalStateException(ConstantUtils.invalidArrayRankMessage(rank));
|
||||
return new ArrayClassDescImpl(elementType, rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType(int rank) {
|
||||
if (rank <= 0) {
|
||||
throw new IllegalArgumentException("rank " + rank + " is not a positive value");
|
||||
}
|
||||
rank += this.rank;
|
||||
ConstantUtils.validateArrayRank(rank);
|
||||
return new ArrayClassDescImpl(elementType, rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArray() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc componentType() {
|
||||
return rank == 1 ? elementType : new ArrayClassDescImpl(elementType, rank - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return elementType.displayName() + "[]".repeat(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
var desc = cachedDescriptorString;
|
||||
if (desc != null)
|
||||
return desc;
|
||||
|
||||
return cachedDescriptorString = computeDescriptor();
|
||||
}
|
||||
|
||||
private String computeDescriptor() {
|
||||
var componentDesc = elementType.descriptorString();
|
||||
StringBuilder sb = new StringBuilder(rank + componentDesc.length());
|
||||
sb.repeat('[', rank);
|
||||
sb.append(componentDesc);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
|
||||
if (elementType.isPrimitive()) {
|
||||
return lookup.findClass(descriptorString());
|
||||
}
|
||||
// Class.forName is slow on class or interface arrays
|
||||
Class<?> clazz = elementType.resolveConstantDesc(lookup);
|
||||
for (int i = 0; i < rank; i++)
|
||||
clazz = clazz.arrayType();
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof ArrayClassDescImpl constant) {
|
||||
return elementType.equals(constant.elementType) && rank == constant.rank;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return descriptorString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ArrayClassDesc[%s, %d]", elementType.displayName(), rank);
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, 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.constant;
|
||||
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
/**
|
||||
* A class or interface descriptor.
|
||||
* Restrictions:
|
||||
* <ul>
|
||||
* <li>Starts with 'L'
|
||||
* <li>Ends with ';'
|
||||
* <li>No '.' or '[' or ';' in the middle
|
||||
* <li>No leading/trailing/consecutive '/'
|
||||
* </ul>
|
||||
*/
|
||||
public final class ClassOrInterfaceDescImpl implements ClassDesc {
|
||||
private final String descriptor;
|
||||
private @Stable String internalName;
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassOrInterfaceDescImpl} from a pre-validated descriptor string
|
||||
* for a class or interface.
|
||||
*/
|
||||
public static ClassOrInterfaceDescImpl ofValidated(String descriptor) {
|
||||
assert ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length())
|
||||
== descriptor.length() : descriptor;
|
||||
assert descriptor.charAt(0) == 'L';
|
||||
return new ClassOrInterfaceDescImpl(descriptor);
|
||||
}
|
||||
|
||||
ClassOrInterfaceDescImpl(String descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public String internalName() {
|
||||
var internalName = this.internalName;
|
||||
if (internalName == null) {
|
||||
this.internalName = internalName = dropFirstAndLastChar(descriptor);
|
||||
}
|
||||
return internalName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType(int rank) {
|
||||
ConstantUtils.validateArrayRank(rank);
|
||||
return ArrayClassDescImpl.ofValidated(this, rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType() {
|
||||
return ArrayClassDescImpl.ofValidated(this, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc nested(String nestedName) {
|
||||
validateMemberName(nestedName, false);
|
||||
String desc = descriptorString();
|
||||
StringBuilder sb = new StringBuilder(desc.length() + nestedName.length() + 1);
|
||||
sb.append(desc, 0, desc.length() - 1).append('$').append(nestedName).append(';');
|
||||
return ofValidated(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc nested(String firstNestedName, String... moreNestedNames) {
|
||||
validateMemberName(firstNestedName, false);
|
||||
// implicit null-check
|
||||
for (String addNestedNames : moreNestedNames) {
|
||||
validateMemberName(addNestedNames, false);
|
||||
}
|
||||
return moreNestedNames.length == 0
|
||||
? nested(firstNestedName)
|
||||
: nested(firstNestedName + "$" + String.join("$", moreNestedNames));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClassOrInterface() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String packageName() {
|
||||
String desc = descriptorString();
|
||||
int index = desc.lastIndexOf('/');
|
||||
return (index == -1) ? "" : internalToBinary(desc.substring(1, index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
String desc = descriptorString();
|
||||
return desc.substring(Math.max(1, desc.lastIndexOf('/') + 1), desc.length() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||
throws ReflectiveOperationException {
|
||||
return lookup.findClass(internalToBinary(internalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this {@linkplain ClassOrInterfaceDescImpl} is
|
||||
* equal to another {@linkplain ClassOrInterfaceDescImpl}. Equality is
|
||||
* determined by the two class descriptors having equal class descriptor
|
||||
* strings.
|
||||
*
|
||||
* @param o the {@code ClassDesc} to compare to this
|
||||
* {@code ClassDesc}
|
||||
* @return {@code true} if the specified {@code ClassDesc}
|
||||
* is equal to this {@code ClassDesc}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof ClassOrInterfaceDescImpl constant) {
|
||||
return descriptor.equals(constant.descriptor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return descriptor.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ClassOrInterfaceDesc[%s]", displayName());
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
package jdk.internal.constant;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.constant.ClassDesc;
|
||||
@ -31,8 +32,6 @@ import java.lang.constant.ConstantDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
@ -50,6 +49,7 @@ public final class ConstantUtils {
|
||||
public static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0];
|
||||
public static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255;
|
||||
public static final ClassDesc CD_module_info = binaryNameToDesc("module-info");
|
||||
public static @Stable ClassDesc CD_Object_array; // set from ConstantDescs, avoid circular initialization
|
||||
|
||||
private static final Set<String> pointyNames = Set.of(ConstantDescs.INIT_NAME, ConstantDescs.CLASS_INIT_NAME);
|
||||
|
||||
@ -70,7 +70,18 @@ public final class ConstantUtils {
|
||||
* @param binaryName a binary name
|
||||
*/
|
||||
public static ClassDesc binaryNameToDesc(String binaryName) {
|
||||
return ReferenceClassDescImpl.ofValidated(concat("L", binaryToInternal(binaryName), ";"));
|
||||
return internalNameToDesc(binaryToInternal(binaryName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a pre-validated internal name
|
||||
* for a class or interface type. Validated version of {@link
|
||||
* ClassDesc#ofInternalName(String)}.
|
||||
*
|
||||
* @param internalName a binary name
|
||||
*/
|
||||
public static ClassDesc internalNameToDesc(String internalName) {
|
||||
return ClassOrInterfaceDescImpl.ofValidated(concat("L", internalName, ";"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,7 +102,21 @@ public final class ConstantUtils {
|
||||
* class or interface or an array type with a non-hidden component type.
|
||||
*/
|
||||
public static ClassDesc referenceClassDesc(Class<?> type) {
|
||||
return ReferenceClassDescImpl.ofValidated(type.descriptorString());
|
||||
return referenceClassDesc(type.descriptorString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a pre-validated descriptor string
|
||||
* for a class or interface type or an array type.
|
||||
*
|
||||
* @param descriptor a field descriptor string for a class or interface type
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ClassDesc referenceClassDesc(String descriptor) {
|
||||
if (descriptor.charAt(0) == '[') {
|
||||
return ArrayClassDescImpl.ofValidatedDescriptor(descriptor);
|
||||
}
|
||||
return ClassOrInterfaceDescImpl.ofValidated(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,6 +153,26 @@ public final class ConstantUtils {
|
||||
return MethodTypeDescImpl.ofValidated(returnDesc, paramDescs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a descriptor string for a class or
|
||||
* interface type or an array type.
|
||||
*
|
||||
* @param descriptor a field descriptor string for a class or interface type
|
||||
* @throws IllegalArgumentException if the descriptor string is not a valid
|
||||
* field descriptor string, or does not describe a class or interface type
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ClassDesc parseReferenceTypeDesc(String descriptor) {
|
||||
int dLen = descriptor.length();
|
||||
int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, dLen);
|
||||
if (len <= 1 || len != dLen)
|
||||
throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
|
||||
if (descriptor.charAt(0) == '[') {
|
||||
return ArrayClassDescImpl.ofValidatedDescriptor(descriptor);
|
||||
}
|
||||
return ClassOrInterfaceDescImpl.ofValidated(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of a binary class name. In particular checks for the presence of
|
||||
* invalid characters in the name.
|
||||
@ -140,8 +185,9 @@ public final class ConstantUtils {
|
||||
public static String validateBinaryClassName(String name) {
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == ';' || ch == '[' || ch == '/')
|
||||
throw new IllegalArgumentException("Invalid class name: " + name);
|
||||
if (ch == ';' || ch == '[' || ch == '/'
|
||||
|| ch == '.' && (i == 0 || i + 1 == name.length() || name.charAt(i - 1) == '.'))
|
||||
throw invalidClassName(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -158,8 +204,9 @@ public final class ConstantUtils {
|
||||
public static String validateInternalClassName(String name) {
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == ';' || ch == '[' || ch == '.')
|
||||
throw new IllegalArgumentException("Invalid class name: " + name);
|
||||
if (ch == ';' || ch == '[' || ch == '.'
|
||||
|| ch == '/' && (i == 0 || i + 1 == name.length() || name.charAt(i - 1) == '/'))
|
||||
throw invalidClassName(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -256,10 +303,24 @@ public final class ConstantUtils {
|
||||
throw new IllegalArgumentException("not a class or interface type: " + classDesc);
|
||||
}
|
||||
|
||||
public static int arrayDepth(String descriptorString) {
|
||||
public static void validateArrayRank(int rank) {
|
||||
// array rank must be representable with u1 and nonzero
|
||||
if (rank == 0 || (rank & ~0xFF) != 0) {
|
||||
throw new IllegalArgumentException(invalidArrayRankMessage(rank));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the array depth on a trusted descriptor.
|
||||
* Uses a simple loop with the assumption that most descriptors have
|
||||
* 0 or very low array depths.
|
||||
*/
|
||||
public static int arrayDepth(String descriptorString, int off) {
|
||||
int depth = 0;
|
||||
while (descriptorString.charAt(depth) == '[')
|
||||
while (descriptorString.charAt(off) == '[') {
|
||||
depth++;
|
||||
off++;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
@ -296,7 +357,22 @@ public final class ConstantUtils {
|
||||
}
|
||||
|
||||
// Pre-verified in MethodTypeDescImpl#ofDescriptor; avoid redundant verification
|
||||
return ReferenceClassDescImpl.ofValidated(descriptor.substring(start, start + len));
|
||||
int arrayDepth = arrayDepth(descriptor, start);
|
||||
if (arrayDepth == 0) {
|
||||
return ClassOrInterfaceDescImpl.ofValidated(descriptor.substring(start, start + len));
|
||||
} else if (arrayDepth + 1 == len) {
|
||||
return ArrayClassDescImpl.ofValidated(forPrimitiveType(descriptor, start + arrayDepth), arrayDepth);
|
||||
} else {
|
||||
return ArrayClassDescImpl.ofValidated(ClassOrInterfaceDescImpl.ofValidated(descriptor.substring(start + arrayDepth, start + len)), arrayDepth);
|
||||
}
|
||||
}
|
||||
|
||||
static String invalidArrayRankMessage(int rank) {
|
||||
return "Array rank must be within [1, 255]: " + rank;
|
||||
}
|
||||
|
||||
static IllegalArgumentException invalidClassName(String className) {
|
||||
return new IllegalArgumentException("Invalid class name: ".concat(className));
|
||||
}
|
||||
|
||||
static IllegalArgumentException badMethodDescriptor(String descriptor) {
|
||||
|
@ -39,13 +39,13 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_void;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import static jdk.internal.constant.ConstantUtils.badMethodDescriptor;
|
||||
import static jdk.internal.constant.ConstantUtils.resolveClassDesc;
|
||||
import static jdk.internal.constant.ConstantUtils.skipOverFieldSignature;
|
||||
import static jdk.internal.constant.ConstantUtils.EMPTY_CLASSDESC;
|
||||
import static jdk.internal.constant.PrimitiveClassDescImpl.CD_void;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
@ -86,7 +86,7 @@ public final class MethodTypeDescImpl implements MethodTypeDesc {
|
||||
}
|
||||
|
||||
private static ClassDesc validateArgument(ClassDesc arg) {
|
||||
if (arg.descriptorString().charAt(0) == 'V') // implicit null check
|
||||
if (requireNonNull(arg) == CD_void)
|
||||
throw new IllegalArgumentException("Void parameters not permitted");
|
||||
return arg;
|
||||
}
|
||||
|
@ -93,6 +93,31 @@ public final class PrimitiveClassDescImpl
|
||||
return this.lazyWrapper = Wrapper.forBasicType(descriptorString().charAt(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType(int rank) {
|
||||
ConstantUtils.validateArrayRank(rank);
|
||||
if (this == CD_void)
|
||||
throw new IllegalArgumentException("not a valid reference type descriptor: " + "[".repeat(rank) + "V");
|
||||
return ArrayClassDescImpl.ofValidated(this, rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc arrayType() {
|
||||
if (this == CD_void)
|
||||
throw new IllegalArgumentException("not a valid reference type descriptor: [V");
|
||||
return ArrayClassDescImpl.ofValidated(this, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName() {
|
||||
return wrapper().primitiveSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
|
@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2024, 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.constant;
|
||||
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import static jdk.internal.constant.ConstantUtils.*;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
|
||||
* interface, or array type. A {@linkplain ReferenceClassDescImpl} corresponds to a
|
||||
* {@code Constant_Class_info} entry in the constant pool of a classfile.
|
||||
*/
|
||||
public final class ReferenceClassDescImpl implements ClassDesc {
|
||||
private final String descriptor;
|
||||
private @Stable String internalName;
|
||||
|
||||
private ReferenceClassDescImpl(String descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a descriptor string for a class or
|
||||
* interface type or an array type.
|
||||
*
|
||||
* @param descriptor a field descriptor string for a class or interface type
|
||||
* @throws IllegalArgumentException if the descriptor string is not a valid
|
||||
* field descriptor string, or does not describe a class or interface type
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ReferenceClassDescImpl of(String descriptor) {
|
||||
int dLen = descriptor.length();
|
||||
int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, dLen);
|
||||
if (len <= 1 || len != dLen)
|
||||
throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
|
||||
return new ReferenceClassDescImpl(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} from a pre-validated descriptor string
|
||||
* for a class or interface type or an array type.
|
||||
*
|
||||
* @param descriptor a field descriptor string for a class or interface type
|
||||
* @jvms 4.3.2 Field Descriptors
|
||||
*/
|
||||
public static ReferenceClassDescImpl ofValidated(String descriptor) {
|
||||
assert ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length())
|
||||
== descriptor.length() : descriptor;
|
||||
return new ReferenceClassDescImpl(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String internalName() {
|
||||
var internalName = this.internalName;
|
||||
if (internalName == null) {
|
||||
var desc = this.descriptor;
|
||||
this.internalName = internalName = desc.charAt(0) == 'L' ? dropFirstAndLastChar(desc) : desc;
|
||||
}
|
||||
|
||||
return internalName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||
throws ReflectiveOperationException {
|
||||
if (isArray()) {
|
||||
if (isPrimitiveArray()) {
|
||||
return lookup.findClass(descriptor);
|
||||
}
|
||||
// Class.forName is slow on class or interface arrays
|
||||
int depth = ConstantUtils.arrayDepth(descriptor);
|
||||
Class<?> clazz = lookup.findClass(internalToBinary(descriptor.substring(depth + 1, descriptor.length() - 1)));
|
||||
for (int i = 0; i < depth; i++)
|
||||
clazz = clazz.arrayType();
|
||||
return clazz;
|
||||
}
|
||||
return lookup.findClass(internalToBinary(internalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the descriptor is one of a primitive array, given this is
|
||||
* already a valid reference type descriptor.
|
||||
*/
|
||||
private boolean isPrimitiveArray() {
|
||||
// All L-type descriptors must end with a semicolon; same for reference
|
||||
// arrays, leaving primitive arrays the only ones without a final semicolon
|
||||
return descriptor.charAt(descriptor.length() - 1) != ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this {@linkplain ReferenceClassDescImpl} is
|
||||
* equal to another {@linkplain ReferenceClassDescImpl}. Equality is
|
||||
* determined by the two class descriptors having equal class descriptor
|
||||
* strings.
|
||||
*
|
||||
* @param o the {@code ClassDesc} to compare to this
|
||||
* {@code ClassDesc}
|
||||
* @return {@code true} if the specified {@code ClassDesc}
|
||||
* is equal to this {@code ClassDesc}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof ReferenceClassDescImpl constant) {
|
||||
return descriptor.equals(constant.descriptor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return descriptor.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ClassDesc[%s]", displayName());
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024, 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
|
||||
@ -40,9 +40,9 @@ import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
/*
|
||||
* @test
|
||||
* @bug 8215510 8283075
|
||||
* @bug 8215510 8283075 8338544
|
||||
* @compile ClassDescTest.java
|
||||
* @run testng ClassDescTest
|
||||
* @summary unit tests for java.lang.constant.ClassDesc
|
||||
@ -68,7 +68,30 @@ public class ClassDescTest extends SymbolicDescTest {
|
||||
assertEquals(r, r.componentType().arrayType());
|
||||
assertEquals(r, r.resolveConstantDesc(LOOKUP).getComponentType().describeConstable().orElseThrow().arrayType());
|
||||
assertEquals(r, Array.newInstance(r.componentType().resolveConstantDesc(LOOKUP), 0).getClass().describeConstable().orElseThrow());
|
||||
} else {
|
||||
assertNull(r.componentType());
|
||||
}
|
||||
|
||||
if (!r.isClassOrInterface()) {
|
||||
assertEquals(r.packageName(), "");
|
||||
}
|
||||
}
|
||||
|
||||
private static String classDisplayName(Class<?> c) {
|
||||
int arrayLevel = 0;
|
||||
while (c.isArray()) {
|
||||
arrayLevel++;
|
||||
c = c.componentType();
|
||||
}
|
||||
String name = c.getName();
|
||||
String simpleClassName;
|
||||
if (c.isPrimitive()) {
|
||||
simpleClassName = name;
|
||||
} else {
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
simpleClassName = lastDot == -1 ? name : name.substring(lastDot + 1);
|
||||
}
|
||||
return simpleClassName + "[]".repeat(arrayLevel);
|
||||
}
|
||||
|
||||
private void testClassDesc(ClassDesc r, Class<?> c) throws ReflectiveOperationException {
|
||||
@ -77,6 +100,13 @@ public class ClassDescTest extends SymbolicDescTest {
|
||||
assertEquals(r.resolveConstantDesc(LOOKUP), c);
|
||||
assertEquals(c.describeConstable().orElseThrow(), r);
|
||||
assertEquals(ClassDesc.ofDescriptor(c.descriptorString()), r);
|
||||
if (r.isArray()) {
|
||||
testClassDesc(r.componentType(), c.componentType());
|
||||
}
|
||||
if (r.isClassOrInterface()) {
|
||||
assertEquals(r.packageName(), c.getPackageName());
|
||||
}
|
||||
assertEquals(r.displayName(), classDisplayName(c));
|
||||
}
|
||||
|
||||
public void testSymbolicDescsConstants() throws ReflectiveOperationException {
|
||||
@ -143,7 +173,8 @@ public class ClassDescTest extends SymbolicDescTest {
|
||||
assertFalse(r.isPrimitive());
|
||||
assertEquals("Ljava/lang/String;", r.descriptorString());
|
||||
assertEquals("String", r.displayName());
|
||||
assertEquals(r.arrayType().resolveConstantDesc(LOOKUP), String[].class);
|
||||
testClassDesc(r.arrayType(), String[].class);
|
||||
testClassDesc(r.arrayType(3), String[][][].class);
|
||||
stringClassDescs.forEach(rr -> assertEquals(r, rr));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user