mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8331724: Refactor j.l.constant implementation to internal package
Reviewed-by: liach, asotona
This commit is contained in:
parent
d84a8fd876
commit
0b0445be28
20 changed files with 364 additions and 192 deletions
|
@ -28,14 +28,19 @@ import java.lang.invoke.MethodHandles;
|
|||
import java.lang.invoke.TypeDescriptor;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.constant.PrimitiveClassDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import static java.lang.constant.ConstantUtils.binaryToInternal;
|
||||
import static java.lang.constant.ConstantUtils.dropLastChar;
|
||||
import static java.lang.constant.ConstantUtils.internalToBinary;
|
||||
import static java.lang.constant.ConstantUtils.validateMemberName;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
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.dropFirstAndLastChar;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
|
@ -77,7 +82,7 @@ public sealed interface ClassDesc
|
|||
* @see ClassDesc#ofInternalName(String)
|
||||
*/
|
||||
static ClassDesc of(String name) {
|
||||
ConstantUtils.validateBinaryClassName(requireNonNull(name));
|
||||
validateBinaryClassName(name);
|
||||
return ClassDesc.ofDescriptor("L" + binaryToInternal(name) + ";");
|
||||
}
|
||||
|
||||
|
@ -103,7 +108,7 @@ public sealed interface ClassDesc
|
|||
* @since 20
|
||||
*/
|
||||
static ClassDesc ofInternalName(String name) {
|
||||
ConstantUtils.validateInternalClassName(requireNonNull(name));
|
||||
validateInternalClassName(name);
|
||||
return ClassDesc.ofDescriptor("L" + name + ";");
|
||||
}
|
||||
|
||||
|
@ -122,11 +127,11 @@ public sealed interface ClassDesc
|
|||
* not in the correct format
|
||||
*/
|
||||
static ClassDesc of(String packageName, String className) {
|
||||
ConstantUtils.validateBinaryClassName(requireNonNull(packageName));
|
||||
validateBinaryClassName(packageName);
|
||||
if (packageName.isEmpty()) {
|
||||
return of(className);
|
||||
}
|
||||
validateMemberName(requireNonNull(className), false);
|
||||
validateMemberName(className, false);
|
||||
return ofDescriptor("L" + binaryToInternal(packageName) +
|
||||
"/" + className + ";");
|
||||
}
|
||||
|
@ -162,7 +167,7 @@ public sealed interface ClassDesc
|
|||
return (descriptor.length() == 1)
|
||||
? Wrapper.forPrimitiveType(descriptor.charAt(0)).classDescriptor()
|
||||
// will throw IAE on descriptor.length == 0 or if array dimensions too long
|
||||
: new ReferenceClassDescImpl(descriptor);
|
||||
: ReferenceClassDescImpl.of(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,13 +180,18 @@ public sealed interface ClassDesc
|
|||
* @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) {
|
||||
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 " +
|
||||
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS + " dimensions");
|
||||
MAX_ARRAY_TYPE_DESC_DIMENSIONS + " dimensions");
|
||||
}
|
||||
return arrayType(1);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,22 +206,22 @@ public sealed interface ClassDesc
|
|||
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||
*/
|
||||
default ClassDesc arrayType(int rank) {
|
||||
int netRank;
|
||||
if (rank <= 0) {
|
||||
throw new IllegalArgumentException("rank " + rank + " is not a positive value");
|
||||
}
|
||||
try {
|
||||
int currentDepth = ConstantUtils.arrayDepth(descriptorString());
|
||||
netRank = Math.addExact(currentDepth, rank);
|
||||
if (netRank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
|
||||
throw new IllegalArgumentException("rank: " + netRank +
|
||||
" exceeds maximum supported dimension of " +
|
||||
ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS);
|
||||
}
|
||||
} catch (ArithmeticException ae) {
|
||||
throw new IllegalArgumentException("Integer overflow in rank computation");
|
||||
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);
|
||||
}
|
||||
return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString());
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,7 +245,10 @@ public sealed interface ClassDesc
|
|||
validateMemberName(nestedName, false);
|
||||
if (!isClassOrInterface())
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
return ClassDesc.ofDescriptor(dropLastChar(descriptorString()) + "$" + nestedName + ";");
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,7 +268,7 @@ public sealed interface ClassDesc
|
|||
if (!isClassOrInterface())
|
||||
throw new IllegalStateException("Outer class is not a class or interface type");
|
||||
validateMemberName(firstNestedName, false);
|
||||
requireNonNull(moreNestedNames);
|
||||
// implicit null-check
|
||||
for (String addNestedNames : moreNestedNames) {
|
||||
validateMemberName(addNestedNames, false);
|
||||
}
|
||||
|
@ -299,7 +312,15 @@ public sealed interface ClassDesc
|
|||
* if this descriptor does not describe an array type
|
||||
*/
|
||||
default ClassDesc componentType() {
|
||||
return isArray() ? ClassDesc.ofDescriptor(descriptorString().substring(1)) : null;
|
||||
if (isArray()) {
|
||||
String desc = descriptorString();
|
||||
if (desc.length() == 2) {
|
||||
return Wrapper.forBasicType(desc.charAt(1)).classDescriptor();
|
||||
} else {
|
||||
return ReferenceClassDescImpl.ofValidated(desc.substring(1));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,9 +333,9 @@ public sealed interface ClassDesc
|
|||
default String packageName() {
|
||||
if (!isClassOrInterface())
|
||||
return "";
|
||||
String className = internalToBinary(ConstantUtils.dropFirstAndLastChar(descriptorString()));
|
||||
int index = className.lastIndexOf('.');
|
||||
return (index == -1) ? "" : className.substring(0, index);
|
||||
String desc = descriptorString();
|
||||
int index = desc.lastIndexOf('/');
|
||||
return (index == -1) ? "" : internalToBinary(desc.substring(1, index));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,11 +353,11 @@ public sealed interface ClassDesc
|
|||
if (isPrimitive())
|
||||
return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveSimpleName();
|
||||
else if (isClassOrInterface()) {
|
||||
return descriptorString().substring(Math.max(1, descriptorString().lastIndexOf('/') + 1),
|
||||
descriptorString().length() - 1);
|
||||
String desc = descriptorString();
|
||||
return desc.substring(Math.max(1, desc.lastIndexOf('/') + 1), desc.length() - 1);
|
||||
}
|
||||
else if (isArray()) {
|
||||
int depth = ConstantUtils.arrayDepth(descriptorString());
|
||||
int depth = arrayDepth(descriptorString());
|
||||
ClassDesc c = this;
|
||||
for (int i=0; i<depth; i++)
|
||||
c = c.componentType();
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import jdk.internal.constant.PrimitiveClassDescImpl;
|
||||
import jdk.internal.constant.ReferenceClassDescImpl;
|
||||
|
||||
import java.lang.Enum.EnumDesc;
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.ConstantBootstraps;
|
||||
|
@ -64,115 +67,115 @@ public final class ConstantDescs {
|
|||
// Don't change the order of these declarations!
|
||||
|
||||
/** {@link ClassDesc} representing {@link Object} */
|
||||
public static final ClassDesc CD_Object = new ReferenceClassDescImpl("Ljava/lang/Object;");
|
||||
public static final ClassDesc CD_Object = ReferenceClassDescImpl.ofValidated("Ljava/lang/Object;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link String} */
|
||||
public static final ClassDesc CD_String = new ReferenceClassDescImpl("Ljava/lang/String;");
|
||||
public static final ClassDesc CD_String = ReferenceClassDescImpl.ofValidated("Ljava/lang/String;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Class} */
|
||||
public static final ClassDesc CD_Class = new ReferenceClassDescImpl("Ljava/lang/Class;");
|
||||
public static final ClassDesc CD_Class = ReferenceClassDescImpl.ofValidated("Ljava/lang/Class;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Number} */
|
||||
public static final ClassDesc CD_Number = new ReferenceClassDescImpl("Ljava/lang/Number;");
|
||||
public static final ClassDesc CD_Number = ReferenceClassDescImpl.ofValidated("Ljava/lang/Number;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Integer} */
|
||||
public static final ClassDesc CD_Integer = new ReferenceClassDescImpl("Ljava/lang/Integer;");
|
||||
public static final ClassDesc CD_Integer = ReferenceClassDescImpl.ofValidated("Ljava/lang/Integer;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Long} */
|
||||
public static final ClassDesc CD_Long = new ReferenceClassDescImpl("Ljava/lang/Long;");
|
||||
public static final ClassDesc CD_Long = ReferenceClassDescImpl.ofValidated("Ljava/lang/Long;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Float} */
|
||||
public static final ClassDesc CD_Float = new ReferenceClassDescImpl("Ljava/lang/Float;");
|
||||
public static final ClassDesc CD_Float = ReferenceClassDescImpl.ofValidated("Ljava/lang/Float;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Double} */
|
||||
public static final ClassDesc CD_Double = new ReferenceClassDescImpl("Ljava/lang/Double;");
|
||||
public static final ClassDesc CD_Double = ReferenceClassDescImpl.ofValidated("Ljava/lang/Double;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Short} */
|
||||
public static final ClassDesc CD_Short = new ReferenceClassDescImpl("Ljava/lang/Short;");
|
||||
public static final ClassDesc CD_Short = ReferenceClassDescImpl.ofValidated("Ljava/lang/Short;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Byte} */
|
||||
public static final ClassDesc CD_Byte = new ReferenceClassDescImpl("Ljava/lang/Byte;");
|
||||
public static final ClassDesc CD_Byte = ReferenceClassDescImpl.ofValidated("Ljava/lang/Byte;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Character} */
|
||||
public static final ClassDesc CD_Character = new ReferenceClassDescImpl("Ljava/lang/Character;");
|
||||
public static final ClassDesc CD_Character = ReferenceClassDescImpl.ofValidated("Ljava/lang/Character;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Boolean} */
|
||||
public static final ClassDesc CD_Boolean = new ReferenceClassDescImpl("Ljava/lang/Boolean;");
|
||||
public static final ClassDesc CD_Boolean = ReferenceClassDescImpl.ofValidated("Ljava/lang/Boolean;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Void} */
|
||||
public static final ClassDesc CD_Void = new ReferenceClassDescImpl("Ljava/lang/Void;");
|
||||
public static final ClassDesc CD_Void = ReferenceClassDescImpl.ofValidated("Ljava/lang/Void;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Throwable} */
|
||||
public static final ClassDesc CD_Throwable = new ReferenceClassDescImpl("Ljava/lang/Throwable;");
|
||||
public static final ClassDesc CD_Throwable = ReferenceClassDescImpl.ofValidated("Ljava/lang/Throwable;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Exception} */
|
||||
public static final ClassDesc CD_Exception = new ReferenceClassDescImpl("Ljava/lang/Exception;");
|
||||
public static final ClassDesc CD_Exception = ReferenceClassDescImpl.ofValidated("Ljava/lang/Exception;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Enum} */
|
||||
public static final ClassDesc CD_Enum = new ReferenceClassDescImpl("Ljava/lang/Enum;");
|
||||
public static final ClassDesc CD_Enum = ReferenceClassDescImpl.ofValidated("Ljava/lang/Enum;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link VarHandle} */
|
||||
public static final ClassDesc CD_VarHandle = new ReferenceClassDescImpl("Ljava/lang/invoke/VarHandle;");
|
||||
public static final ClassDesc CD_VarHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/VarHandle;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandles} */
|
||||
public static final ClassDesc CD_MethodHandles = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandles;");
|
||||
public static final ClassDesc CD_MethodHandles = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandles.Lookup} */
|
||||
public static final ClassDesc CD_MethodHandles_Lookup = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandles$Lookup;");
|
||||
public static final ClassDesc CD_MethodHandles_Lookup = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandles$Lookup;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandle} */
|
||||
public static final ClassDesc CD_MethodHandle = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodHandle;");
|
||||
public static final ClassDesc CD_MethodHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodHandle;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodType} */
|
||||
public static final ClassDesc CD_MethodType = new ReferenceClassDescImpl("Ljava/lang/invoke/MethodType;");
|
||||
public static final ClassDesc CD_MethodType = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/MethodType;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link CallSite} */
|
||||
public static final ClassDesc CD_CallSite = new ReferenceClassDescImpl("Ljava/lang/invoke/CallSite;");
|
||||
public static final ClassDesc CD_CallSite = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/CallSite;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Collection} */
|
||||
public static final ClassDesc CD_Collection = new ReferenceClassDescImpl("Ljava/util/Collection;");
|
||||
public static final ClassDesc CD_Collection = ReferenceClassDescImpl.ofValidated("Ljava/util/Collection;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link List} */
|
||||
public static final ClassDesc CD_List = new ReferenceClassDescImpl("Ljava/util/List;");
|
||||
public static final ClassDesc CD_List = ReferenceClassDescImpl.ofValidated("Ljava/util/List;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Set} */
|
||||
public static final ClassDesc CD_Set = new ReferenceClassDescImpl("Ljava/util/Set;");
|
||||
public static final ClassDesc CD_Set = ReferenceClassDescImpl.ofValidated("Ljava/util/Set;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link Map} */
|
||||
public static final ClassDesc CD_Map = new ReferenceClassDescImpl("Ljava/util/Map;");
|
||||
public static final ClassDesc CD_Map = ReferenceClassDescImpl.ofValidated("Ljava/util/Map;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ConstantDesc} */
|
||||
public static final ClassDesc CD_ConstantDesc = new ReferenceClassDescImpl("Ljava/lang/constant/ConstantDesc;");
|
||||
public static final ClassDesc CD_ConstantDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/ConstantDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ClassDesc} */
|
||||
public static final ClassDesc CD_ClassDesc = new ReferenceClassDescImpl("Ljava/lang/constant/ClassDesc;");
|
||||
public static final ClassDesc CD_ClassDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/ClassDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link EnumDesc} */
|
||||
public static final ClassDesc CD_EnumDesc = new ReferenceClassDescImpl("Ljava/lang/Enum$EnumDesc;");
|
||||
public static final ClassDesc CD_EnumDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/Enum$EnumDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodTypeDesc} */
|
||||
public static final ClassDesc CD_MethodTypeDesc = new ReferenceClassDescImpl("Ljava/lang/constant/MethodTypeDesc;");
|
||||
public static final ClassDesc CD_MethodTypeDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/MethodTypeDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link MethodHandleDesc} */
|
||||
public static final ClassDesc CD_MethodHandleDesc = new ReferenceClassDescImpl("Ljava/lang/constant/MethodHandleDesc;");
|
||||
public static final ClassDesc CD_MethodHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/MethodHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DirectMethodHandleDesc} */
|
||||
public static final ClassDesc CD_DirectMethodHandleDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DirectMethodHandleDesc;");
|
||||
public static final ClassDesc CD_DirectMethodHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link VarHandleDesc} */
|
||||
public static final ClassDesc CD_VarHandleDesc = new ReferenceClassDescImpl("Ljava/lang/invoke/VarHandle$VarHandleDesc;");
|
||||
public static final ClassDesc CD_VarHandleDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/VarHandle$VarHandleDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
|
||||
public static final ClassDesc CD_MethodHandleDesc_Kind = new ReferenceClassDescImpl("Ljava/lang/constant/DirectMethodHandleDesc$Kind;");
|
||||
public static final ClassDesc CD_MethodHandleDesc_Kind = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DirectMethodHandleDesc$Kind;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DynamicConstantDesc} */
|
||||
public static final ClassDesc CD_DynamicConstantDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DynamicConstantDesc;");
|
||||
public static final ClassDesc CD_DynamicConstantDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DynamicConstantDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link DynamicCallSiteDesc} */
|
||||
public static final ClassDesc CD_DynamicCallSiteDesc = new ReferenceClassDescImpl("Ljava/lang/constant/DynamicCallSiteDesc;");
|
||||
public static final ClassDesc CD_DynamicCallSiteDesc = ReferenceClassDescImpl.ofValidated("Ljava/lang/constant/DynamicCallSiteDesc;");
|
||||
|
||||
/** {@link ClassDesc} representing {@link ConstantBootstraps} */
|
||||
public static final ClassDesc CD_ConstantBootstraps = new ReferenceClassDescImpl("Ljava/lang/invoke/ConstantBootstraps;");
|
||||
public static final ClassDesc CD_ConstantBootstraps = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/ConstantBootstraps;");
|
||||
|
||||
private static final ClassDesc[] INDY_BOOTSTRAP_ARGS = {
|
||||
CD_MethodHandles_Lookup,
|
||||
|
|
|
@ -1,315 +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 java.lang.constant;
|
||||
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Helper methods for the implementation of {@code java.lang.constant}.
|
||||
*/
|
||||
class ConstantUtils {
|
||||
/** an empty constant descriptor */
|
||||
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
|
||||
static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[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(ConstantDescs.INIT_NAME, ConstantDescs.CLASS_INIT_NAME);
|
||||
|
||||
/**
|
||||
* Validates the correctness of a binary class name. In particular checks for the presence of
|
||||
* invalid characters in the name.
|
||||
*
|
||||
* @param name the class name
|
||||
* @return the class name passed if valid
|
||||
* @throws IllegalArgumentException if the class name is invalid
|
||||
*/
|
||||
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);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of an internal class name.
|
||||
* In particular checks for the presence of invalid characters in the name.
|
||||
*
|
||||
* @param name the class name
|
||||
* @return the class name passed if valid
|
||||
* @throws IllegalArgumentException if the class name is invalid
|
||||
*/
|
||||
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);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of a binary package name.
|
||||
* In particular checks for the presence of invalid characters in the name.
|
||||
* Empty package name is allowed.
|
||||
*
|
||||
* @param name the package name
|
||||
* @return the package name passed if valid
|
||||
* @throws IllegalArgumentException if the package name is invalid
|
||||
* @throws NullPointerException if the package name is {@code null}
|
||||
*/
|
||||
public static String validateBinaryPackageName(String name) {
|
||||
for (int i=0; i<name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == ';' || ch == '[' || ch == '/')
|
||||
throw new IllegalArgumentException("Invalid package name: " + name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of an internal package name.
|
||||
* In particular checks for the presence of invalid characters in the name.
|
||||
* Empty package name is allowed.
|
||||
*
|
||||
* @param name the package name
|
||||
* @return the package name passed if valid
|
||||
* @throws IllegalArgumentException if the package name is invalid
|
||||
* @throws NullPointerException if the package name is {@code null}
|
||||
*/
|
||||
public static String validateInternalPackageName(String name) {
|
||||
for (int i=0; i<name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == ';' || ch == '[' || ch == '.')
|
||||
throw new IllegalArgumentException("Invalid package name: " + name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the correctness of a module name.
|
||||
* In particular checks for the presence of invalid characters in the name.
|
||||
* Empty module name is allowed.
|
||||
*
|
||||
* {@jvms 4.2.3} Module and Package Names
|
||||
*
|
||||
* @param name the module name
|
||||
* @return the module name passed if valid
|
||||
* @throws IllegalArgumentException if the module name is invalid
|
||||
* @throws NullPointerException if the module name is {@code null}
|
||||
*/
|
||||
public static String validateModuleName(String name) {
|
||||
for (int i=name.length() - 1; i >= 0; i--) {
|
||||
char ch = name.charAt(i);
|
||||
if ((ch >= '\u0000' && ch <= '\u001F')
|
||||
|| ((ch == '\\' || ch == ':' || ch =='@') && (i == 0 || name.charAt(--i) != '\\')))
|
||||
throw new IllegalArgumentException("Invalid module name: " + name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a member name
|
||||
*
|
||||
* @param name the name of the member
|
||||
* @return the name passed if valid
|
||||
* @throws IllegalArgumentException if the member name is invalid
|
||||
*/
|
||||
public static String validateMemberName(String name, boolean method) {
|
||||
if (name.length() == 0)
|
||||
throw new IllegalArgumentException("zero-length member name");
|
||||
for (int i=0; i<name.length(); i++) {
|
||||
char ch = name.charAt(i);
|
||||
if (ch == '.' || ch == ';' || ch == '[' || ch == '/')
|
||||
throw new IllegalArgumentException("Invalid member name: " + name);
|
||||
if (method && (ch == '<' || ch == '>')) {
|
||||
if (!pointyNames.contains(name))
|
||||
throw new IllegalArgumentException("Invalid member name: " + name);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static void validateClassOrInterface(ClassDesc classDesc) {
|
||||
if (!classDesc.isClassOrInterface())
|
||||
throw new IllegalArgumentException("not a class or interface type: " + classDesc);
|
||||
}
|
||||
|
||||
static int arrayDepth(String descriptorString) {
|
||||
int depth = 0;
|
||||
while (descriptorString.charAt(depth) == '[')
|
||||
depth++;
|
||||
return depth;
|
||||
}
|
||||
|
||||
static String binaryToInternal(String name) {
|
||||
return name.replace('.', '/');
|
||||
}
|
||||
|
||||
static String internalToBinary(String name) {
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
static String dropLastChar(String s) {
|
||||
return s.substring(0, s.length() - 1);
|
||||
}
|
||||
|
||||
static String dropFirstAndLastChar(String s) {
|
||||
return s.substring(1, s.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a method descriptor string, and return a list of field descriptor
|
||||
* strings, return type first, then parameter types
|
||||
*
|
||||
* @param descriptor the descriptor string
|
||||
* @return the list of types
|
||||
* @throws IllegalArgumentException if the descriptor string is not valid
|
||||
*/
|
||||
static List<ClassDesc> parseMethodDescriptor(String descriptor) {
|
||||
int cur = 0, end = descriptor.length();
|
||||
ArrayList<ClassDesc> ptypes = new ArrayList<>();
|
||||
ptypes.add(null); // placeholder for return type
|
||||
|
||||
if (cur >= end || descriptor.charAt(cur) != '(')
|
||||
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
|
||||
|
||||
++cur; // skip '('
|
||||
while (cur < end && descriptor.charAt(cur) != ')') {
|
||||
int len = skipOverFieldSignature(descriptor, cur, end, false);
|
||||
if (len == 0)
|
||||
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
|
||||
ptypes.add(resolveClassDesc(descriptor, cur, len));
|
||||
cur += len;
|
||||
}
|
||||
if (cur >= end)
|
||||
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
|
||||
++cur; // skip ')'
|
||||
|
||||
int rLen = skipOverFieldSignature(descriptor, cur, end, true);
|
||||
if (rLen == 0 || cur + rLen != end)
|
||||
throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
|
||||
ptypes.set(0, resolveClassDesc(descriptor, cur, rLen));
|
||||
return ptypes;
|
||||
}
|
||||
|
||||
private static ClassDesc resolveClassDesc(String descriptor, int start, int len) {
|
||||
if (len == 1) {
|
||||
return Wrapper.forPrimitiveType(descriptor.charAt(start)).classDescriptor();
|
||||
}
|
||||
return ClassDesc.ofDescriptor(descriptor.substring(start, start + len));
|
||||
}
|
||||
|
||||
private static final char JVM_SIGNATURE_ARRAY = '[';
|
||||
private static final char JVM_SIGNATURE_BYTE = 'B';
|
||||
private static final char JVM_SIGNATURE_CHAR = 'C';
|
||||
private static final char JVM_SIGNATURE_CLASS = 'L';
|
||||
private static final char JVM_SIGNATURE_ENDCLASS = ';';
|
||||
private static final char JVM_SIGNATURE_ENUM = 'E';
|
||||
private static final char JVM_SIGNATURE_FLOAT = 'F';
|
||||
private static final char JVM_SIGNATURE_DOUBLE = 'D';
|
||||
private static final char JVM_SIGNATURE_FUNC = '(';
|
||||
private static final char JVM_SIGNATURE_ENDFUNC = ')';
|
||||
private static final char JVM_SIGNATURE_INT = 'I';
|
||||
private static final char JVM_SIGNATURE_LONG = 'J';
|
||||
private static final char JVM_SIGNATURE_SHORT = 'S';
|
||||
private static final char JVM_SIGNATURE_VOID = 'V';
|
||||
private static final char JVM_SIGNATURE_BOOLEAN = 'Z';
|
||||
|
||||
/**
|
||||
* Validates that the characters at [start, end) within the provided string
|
||||
* describe a valid field type descriptor.
|
||||
* @param descriptor the descriptor string
|
||||
* @param start the starting index into the string
|
||||
* @param end the ending index within the string
|
||||
* @param voidOK is void acceptable?
|
||||
* @return the length of the descriptor, or 0 if it is not a descriptor
|
||||
* @throws IllegalArgumentException if the descriptor string is not valid
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
static int skipOverFieldSignature(String descriptor, int start, int end, boolean voidOK) {
|
||||
int arrayDim = 0;
|
||||
int index = start;
|
||||
while (index < end) {
|
||||
switch (descriptor.charAt(index)) {
|
||||
case JVM_SIGNATURE_VOID: if (!voidOK) { return 0; }
|
||||
case JVM_SIGNATURE_BOOLEAN:
|
||||
case JVM_SIGNATURE_BYTE:
|
||||
case JVM_SIGNATURE_CHAR:
|
||||
case JVM_SIGNATURE_SHORT:
|
||||
case JVM_SIGNATURE_INT:
|
||||
case JVM_SIGNATURE_FLOAT:
|
||||
case JVM_SIGNATURE_LONG:
|
||||
case JVM_SIGNATURE_DOUBLE:
|
||||
return index - start + 1;
|
||||
case JVM_SIGNATURE_CLASS:
|
||||
// state variable for detection of illegal states, such as:
|
||||
// empty unqualified name, '//', leading '/', or trailing '/'
|
||||
boolean legal = false;
|
||||
while (++index < end) {
|
||||
switch (descriptor.charAt(index)) {
|
||||
case ';' -> {
|
||||
// illegal state on parser exit indicates empty unqualified name or trailing '/'
|
||||
return legal ? index - start + 1 : 0;
|
||||
}
|
||||
case '.', '[' -> {
|
||||
// do not permit '.' or '['
|
||||
return 0;
|
||||
}
|
||||
case '/' -> {
|
||||
// illegal state when received '/' indicates '//' or leading '/'
|
||||
if (!legal) return 0;
|
||||
legal = false;
|
||||
}
|
||||
default ->
|
||||
legal = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case JVM_SIGNATURE_ARRAY:
|
||||
arrayDim++;
|
||||
if (arrayDim > 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));
|
||||
}
|
||||
// The rest of what's there better be a legal descriptor
|
||||
index++;
|
||||
voidOK = false;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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
|
||||
|
@ -26,9 +26,8 @@ package java.lang.constant;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.constant.DirectMethodHandleDescImpl;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import static java.lang.invoke.MethodHandleInfo.REF_getField;
|
||||
|
@ -89,7 +88,7 @@ public sealed interface DirectMethodHandleDesc
|
|||
*/
|
||||
public final boolean isInterface;
|
||||
Kind(int refKind) {
|
||||
this(refKind, false);
|
||||
this.refKind = refKind; this.isInterface = false;
|
||||
}
|
||||
|
||||
Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
|
||||
|
@ -179,23 +178,6 @@ public sealed interface DirectMethodHandleDesc
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this {@code Kind} correspond to a virtual method invocation?
|
||||
*
|
||||
* @return if this {@code Kind} corresponds to a virtual method invocation
|
||||
*/
|
||||
boolean isVirtualMethod() {
|
||||
switch (this) {
|
||||
case VIRTUAL:
|
||||
case SPECIAL:
|
||||
case INTERFACE_VIRTUAL:
|
||||
case INTERFACE_SPECIAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_void;
|
||||
import static java.lang.constant.ConstantUtils.validateClassOrInterface;
|
||||
import static java.lang.constant.ConstantUtils.validateMemberName;
|
||||
import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
|
||||
* {@link MethodHandle}. A {@linkplain DirectMethodHandleDescImpl} corresponds to
|
||||
* a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
|
||||
*/
|
||||
final class DirectMethodHandleDescImpl implements DirectMethodHandleDesc {
|
||||
|
||||
private final Kind kind;
|
||||
private final ClassDesc owner;
|
||||
private final String name;
|
||||
private final MethodTypeDesc invocationType;
|
||||
|
||||
/**
|
||||
* Constructs a {@linkplain DirectMethodHandleDescImpl} for a method or field
|
||||
* from a kind, owner, name, and type
|
||||
*
|
||||
* @param kind the kind of the method handle
|
||||
* @param owner the declaring class or interface for the method
|
||||
* @param name the unqualified name of the method (ignored if {@code kind} is {@code CONSTRUCTOR})
|
||||
* @param type the lookup type of the method
|
||||
* @throws NullPointerException if any non-ignored argument is null
|
||||
* @throws IllegalArgumentException if {@code kind} describes a field accessor,
|
||||
* and {@code type} is not consistent with that kind of field accessor, or if
|
||||
* {@code kind} describes a constructor, and the return type of {@code type}
|
||||
* is not {@code void}
|
||||
* @jvms 4.2.2 Unqualified Names
|
||||
*/
|
||||
DirectMethodHandleDescImpl(Kind kind, ClassDesc owner, String name, MethodTypeDesc type) {
|
||||
if (kind == CONSTRUCTOR)
|
||||
name = "<init>";
|
||||
|
||||
requireNonNull(kind);
|
||||
validateClassOrInterface(owner);
|
||||
validateMemberName(name, true);
|
||||
requireNonNull(type);
|
||||
|
||||
switch (kind) {
|
||||
case CONSTRUCTOR -> validateConstructor(type);
|
||||
case GETTER -> validateFieldType(type, false, true);
|
||||
case SETTER -> validateFieldType(type, true, true);
|
||||
case STATIC_GETTER -> validateFieldType(type, false, false);
|
||||
case STATIC_SETTER -> validateFieldType(type, true, false);
|
||||
}
|
||||
|
||||
this.kind = kind;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
if (kind.isVirtualMethod())
|
||||
this.invocationType = type.insertParameterTypes(0, owner);
|
||||
else if (kind == CONSTRUCTOR)
|
||||
this.invocationType = type.changeReturnType(owner);
|
||||
else
|
||||
this.invocationType = type;
|
||||
}
|
||||
|
||||
private static void validateFieldType(MethodTypeDesc type, boolean isSetter, boolean isVirtual) {
|
||||
boolean isVoid = type.returnType().descriptorString().equals("V");
|
||||
int expectedParams = (isSetter ? 1 : 0) + (isVirtual ? 1 : 0);
|
||||
if (isVoid != isSetter
|
||||
|| type.parameterCount() != expectedParams
|
||||
|| (isVirtual && type.parameterType(0).isPrimitive())) {
|
||||
String expectedType = String.format("(%s%s)%s", (isVirtual ? "R" : ""),
|
||||
(isSetter ? "T" : ""), (isSetter ? "V" : "T"));
|
||||
throw new IllegalArgumentException(String.format("Expected type of %s for getter, found %s", expectedType, type));
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateConstructor(MethodTypeDesc type) {
|
||||
if (!type.returnType().descriptorString().equals("V")) {
|
||||
throw new IllegalArgumentException(String.format("Expected type of (T*)V for constructor, found %s", type));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Kind kind() { return kind; }
|
||||
|
||||
@Override
|
||||
public int refKind() { return kind.refKind; }
|
||||
|
||||
@Override
|
||||
public boolean isOwnerInterface() { return kind.isInterface; }
|
||||
|
||||
@Override
|
||||
public ClassDesc owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String methodName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodTypeDesc invocationType() {
|
||||
return invocationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String lookupDescriptor() {
|
||||
return switch (kind) {
|
||||
case VIRTUAL,
|
||||
SPECIAL,
|
||||
INTERFACE_VIRTUAL,
|
||||
INTERFACE_SPECIAL -> invocationType.dropParameterTypes(0, 1).descriptorString();
|
||||
case STATIC,
|
||||
INTERFACE_STATIC -> invocationType.descriptorString();
|
||||
case CONSTRUCTOR -> invocationType.changeReturnType(CD_void).descriptorString();
|
||||
case GETTER,
|
||||
STATIC_GETTER -> invocationType.returnType().descriptorString();
|
||||
case SETTER -> invocationType.parameterType(1).descriptorString();
|
||||
case STATIC_SETTER -> invocationType.parameterType(0).descriptorString();
|
||||
default -> throw new IllegalStateException(kind.toString());
|
||||
};
|
||||
}
|
||||
|
||||
public MethodHandle resolveConstantDesc(MethodHandles.Lookup lookup)
|
||||
throws ReflectiveOperationException {
|
||||
Class<?> resolvedOwner = owner.resolveConstantDesc(lookup);
|
||||
MethodType invocationType = this.invocationType().resolveConstantDesc(lookup);
|
||||
return switch (kind) {
|
||||
case STATIC,
|
||||
INTERFACE_STATIC -> lookup.findStatic(resolvedOwner, name, invocationType);
|
||||
case VIRTUAL,
|
||||
INTERFACE_VIRTUAL -> lookup.findVirtual(resolvedOwner, name, invocationType.dropParameterTypes(0, 1));
|
||||
case SPECIAL,
|
||||
INTERFACE_SPECIAL -> lookup.findSpecial(resolvedOwner, name, invocationType.dropParameterTypes(0, 1), lookup.lookupClass());
|
||||
case CONSTRUCTOR -> lookup.findConstructor(resolvedOwner, invocationType.changeReturnType(void.class));
|
||||
case GETTER -> lookup.findGetter(resolvedOwner, name, invocationType.returnType());
|
||||
case STATIC_GETTER -> lookup.findStaticGetter(resolvedOwner, name, invocationType.returnType());
|
||||
case SETTER -> lookup.findSetter(resolvedOwner, name, invocationType.parameterType(1));
|
||||
case STATIC_SETTER -> lookup.findStaticSetter(resolvedOwner, name, invocationType.parameterType(0));
|
||||
default -> throw new IllegalStateException(kind.name());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this {@linkplain DirectMethodHandleDescImpl} is
|
||||
* equal to another {@linkplain DirectMethodHandleDescImpl}. Equality is
|
||||
* determined by the two descriptors having equal kind, owner, name, and type
|
||||
* descriptor.
|
||||
* @param o a {@code DirectMethodHandleDescImpl} to compare to this
|
||||
* {@code DirectMethodHandleDescImpl}
|
||||
* @return {@code true} if the specified {@code DirectMethodHandleDescImpl}
|
||||
* is equal to this {@code DirectMethodHandleDescImpl}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DirectMethodHandleDescImpl desc = (DirectMethodHandleDescImpl) o;
|
||||
return kind == desc.kind &&
|
||||
Objects.equals(owner, desc.owner) &&
|
||||
Objects.equals(name, desc.name) &&
|
||||
Objects.equals(invocationType, desc.invocationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(kind, owner, name, invocationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MethodHandleDesc[%s/%s::%s%s]", kind, owner.displayName(), name, invocationType.displayDescriptor());
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
@ -32,10 +32,10 @@ import java.util.Objects;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_String;
|
||||
import static java.lang.constant.ConstantUtils.EMPTY_CONSTANTDESC;
|
||||
import static java.lang.constant.ConstantUtils.validateMemberName;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static jdk.internal.constant.ConstantUtils.EMPTY_CONSTANTDESC;
|
||||
import static jdk.internal.constant.ConstantUtils.validateMemberName;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for an
|
||||
|
|
|
@ -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
|
||||
|
@ -39,10 +39,10 @@ import java.util.stream.Stream;
|
|||
import static java.lang.constant.ConstantDescs.CD_Class;
|
||||
import static java.lang.constant.ConstantDescs.CD_VarHandle;
|
||||
import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
|
||||
import static java.lang.constant.ConstantUtils.EMPTY_CONSTANTDESC;
|
||||
import static java.lang.constant.ConstantUtils.validateMemberName;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static jdk.internal.constant.ConstantUtils.EMPTY_CONSTANTDESC;
|
||||
import static jdk.internal.constant.ConstantUtils.validateMemberName;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
|
|
|
@ -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
|
||||
|
@ -28,6 +28,8 @@ import java.lang.invoke.MethodHandle;
|
|||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import jdk.internal.constant.DirectMethodHandleDescImpl;
|
||||
|
||||
import static java.lang.constant.ConstantDescs.CD_void;
|
||||
import static java.lang.constant.DirectMethodHandleDesc.Kind.CONSTRUCTOR;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -31,6 +31,11 @@ import java.util.List;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.MethodTypeDescImpl;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
* {@linkplain MethodType} constant.
|
||||
|
@ -64,7 +69,7 @@ public sealed interface MethodTypeDesc
|
|||
* @since 21
|
||||
*/
|
||||
static MethodTypeDesc of(ClassDesc returnDesc) {
|
||||
return MethodTypeDescImpl.ofTrusted(returnDesc, ConstantUtils.EMPTY_CLASSDESC);
|
||||
return MethodTypeDescImpl.ofValidated(requireNonNull(returnDesc), ConstantUtils.EMPTY_CLASSDESC);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,242 +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 java.lang.constant;
|
||||
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for a
|
||||
* {@link MethodType}. A {@linkplain MethodTypeDescImpl} corresponds to a
|
||||
* {@code Constant_MethodType_info} entry in the constant pool of a classfile.
|
||||
*/
|
||||
final class MethodTypeDescImpl implements MethodTypeDesc {
|
||||
private final ClassDesc returnType;
|
||||
private final @Stable ClassDesc[] argTypes;
|
||||
private @Stable String cachedDescriptorString;
|
||||
|
||||
/**
|
||||
* Constructs a {@linkplain MethodTypeDesc} with the specified return type
|
||||
* and a trusted and already-validated parameter types array.
|
||||
*
|
||||
* @param returnType a {@link ClassDesc} describing the return type
|
||||
* @param validatedArgTypes {@link ClassDesc}s describing the trusted and validated parameter types
|
||||
*/
|
||||
private MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] validatedArgTypes) {
|
||||
this.returnType = returnType;
|
||||
this.argTypes = validatedArgTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@linkplain MethodTypeDesc} with the specified return type
|
||||
* and a trusted parameter types array, which will be validated.
|
||||
*
|
||||
* @param returnType a {@link ClassDesc} describing the return type
|
||||
* @param trustedArgTypes {@link ClassDesc}s describing the trusted parameter types
|
||||
*/
|
||||
static MethodTypeDescImpl ofTrusted(ClassDesc returnType, ClassDesc[] trustedArgTypes) {
|
||||
requireNonNull(returnType);
|
||||
if (trustedArgTypes.length == 0) // implicit null check
|
||||
return new MethodTypeDescImpl(returnType, ConstantUtils.EMPTY_CLASSDESC);
|
||||
|
||||
for (ClassDesc cd : trustedArgTypes)
|
||||
if (cd.descriptorString().charAt(0) == 'V') // implicit null check
|
||||
throw new IllegalArgumentException("Void parameters not permitted");
|
||||
|
||||
return new MethodTypeDescImpl(returnType, trustedArgTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain MethodTypeDescImpl} given a method descriptor string.
|
||||
*
|
||||
* @param descriptor the method descriptor string
|
||||
* @return a {@linkplain MethodTypeDescImpl} describing the desired method type
|
||||
* @throws IllegalArgumentException if the descriptor string is not a valid
|
||||
* method descriptor
|
||||
* @jvms 4.3.3 Method Descriptors
|
||||
*/
|
||||
static MethodTypeDescImpl ofDescriptor(String descriptor) {
|
||||
// Implicit null-check of descriptor
|
||||
List<ClassDesc> ptypes = ConstantUtils.parseMethodDescriptor(descriptor);
|
||||
int args = ptypes.size() - 1;
|
||||
ClassDesc[] paramTypes = args > 0
|
||||
? ptypes.subList(1, args + 1).toArray(ConstantUtils.EMPTY_CLASSDESC)
|
||||
: ConstantUtils.EMPTY_CLASSDESC;
|
||||
|
||||
MethodTypeDescImpl result = ofTrusted(ptypes.get(0), paramTypes);
|
||||
result.cachedDescriptorString = descriptor;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClassDesc returnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int parameterCount() {
|
||||
return argTypes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc parameterType(int index) {
|
||||
return argTypes[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClassDesc> parameterList() {
|
||||
return List.of(argTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDesc[] parameterArray() {
|
||||
return argTypes.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodTypeDesc changeReturnType(ClassDesc returnType) {
|
||||
return new MethodTypeDescImpl(requireNonNull(returnType), argTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
|
||||
ClassDesc[] newArgs = argTypes.clone();
|
||||
newArgs[index] = paramType;
|
||||
return ofTrusted(returnType, newArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodTypeDesc dropParameterTypes(int start, int end) {
|
||||
Objects.checkIndex(start, argTypes.length);
|
||||
Objects.checkFromToIndex(start, end, argTypes.length);
|
||||
|
||||
ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
|
||||
if (start > 0) {
|
||||
System.arraycopy(argTypes, 0, newArgs, 0, start);
|
||||
}
|
||||
if (end < argTypes.length) {
|
||||
System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
|
||||
}
|
||||
return ofTrusted(returnType, newArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
|
||||
if (pos < 0 || pos > argTypes.length)
|
||||
throw new IndexOutOfBoundsException(pos);
|
||||
|
||||
ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
|
||||
if (pos > 0) {
|
||||
System.arraycopy(argTypes, 0, newArgs, 0, pos);
|
||||
}
|
||||
System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
|
||||
if (pos < argTypes.length) {
|
||||
System.arraycopy(argTypes, pos, newArgs, pos + paramTypes.length, argTypes.length - pos);
|
||||
}
|
||||
return ofTrusted(returnType, newArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
var desc = this.cachedDescriptorString;
|
||||
if (desc != null)
|
||||
return desc;
|
||||
|
||||
int len = 2 + returnType.descriptorString().length();
|
||||
for (ClassDesc argType : argTypes) {
|
||||
len += argType.descriptorString().length();
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(len).append('(');
|
||||
for (ClassDesc argType : argTypes) {
|
||||
sb.append(argType.descriptorString());
|
||||
}
|
||||
desc = sb.append(')').append(returnType.descriptorString()).toString();
|
||||
cachedDescriptorString = desc;
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
|
||||
@SuppressWarnings("removal")
|
||||
MethodType mtype = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public MethodType run() {
|
||||
return MethodType.fromMethodDescriptorString(descriptorString(),
|
||||
lookup.lookupClass().getClassLoader());
|
||||
}
|
||||
});
|
||||
|
||||
// let's check that the lookup has access to all the types in the method type
|
||||
lookup.accessClass(mtype.returnType());
|
||||
for (Class<?> paramType: mtype.parameterArray()) {
|
||||
lookup.accessClass(paramType);
|
||||
}
|
||||
return mtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this {@linkplain MethodTypeDescImpl} is
|
||||
* equal to another {@linkplain MethodTypeDescImpl}. Equality is
|
||||
* determined by the two descriptors having equal return types and argument
|
||||
* types.
|
||||
*
|
||||
* @param o the {@code MethodTypeDescImpl} to compare to this
|
||||
* {@code MethodTypeDescImpl}
|
||||
* @return {@code true} if the specified {@code MethodTypeDescImpl}
|
||||
* is equal to this {@code MethodTypeDescImpl}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MethodTypeDescImpl constant = (MethodTypeDescImpl) o;
|
||||
|
||||
return returnType.equals(constant.returnType)
|
||||
&& Arrays.equals(argTypes, constant.argTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = returnType.hashCode();
|
||||
result = 31 * result + Arrays.hashCode(argTypes);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MethodTypeDesc[%s]", displayDescriptor());
|
||||
}
|
||||
}
|
|
@ -24,6 +24,9 @@
|
|||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.ModuleDescImpl;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
/*
|
||||
* Implementation of {@code ModuleDesc}
|
||||
* @param name must have been validated
|
||||
*/
|
||||
record ModuleDescImpl(String name) implements ModuleDesc {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ModuleDesc[%s]", name());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
|
@ -24,6 +24,9 @@
|
|||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import jdk.internal.constant.ConstantUtils;
|
||||
import jdk.internal.constant.PackageDescImpl;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
/*
|
||||
* Implementation of {@code PackageDesc}
|
||||
* @param internalName must have been validated
|
||||
*/
|
||||
record PackageDescImpl(String internalName) implements PackageDesc {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PackageDesc[%s]", name());
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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 java.lang.constant;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A <a href="package-summary.html#nominal">nominal descriptor</a> for the class
|
||||
* constant corresponding to a primitive type (e.g., {@code int.class}).
|
||||
*/
|
||||
final class PrimitiveClassDescImpl
|
||||
extends DynamicConstantDesc<Class<?>> implements ClassDesc {
|
||||
|
||||
private final String descriptor;
|
||||
|
||||
/**
|
||||
* Creates a {@linkplain ClassDesc} given a descriptor string for a primitive
|
||||
* type.
|
||||
*
|
||||
* @param descriptor the descriptor string, which must be a one-character
|
||||
* string corresponding to one of the nine base types
|
||||
* @throws IllegalArgumentException if the descriptor string does not
|
||||
* describe a valid primitive type
|
||||
* @jvms 4.3 Descriptors
|
||||
*/
|
||||
PrimitiveClassDescImpl(String descriptor) {
|
||||
super(ConstantDescs.BSM_PRIMITIVE_CLASS, requireNonNull(descriptor), ConstantDescs.CD_Class);
|
||||
if (descriptor.length() != 1
|
||||
|| "VIJCSBFDZ".indexOf(descriptor.charAt(0)) < 0)
|
||||
throw new IllegalArgumentException(String.format("not a valid primitive type descriptor: %s", descriptor));
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) {
|
||||
return Wrapper.forBasicType(descriptorString().charAt(0)).primitiveType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PrimitiveClassDesc[%s]", displayName());
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.constant;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
import static java.lang.constant.ConstantUtils.*;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
final class ReferenceClassDescImpl implements ClassDesc {
|
||||
private final String 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
|
||||
*/
|
||||
ReferenceClassDescImpl(String descriptor) {
|
||||
int dLen = descriptor.length();
|
||||
int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, dLen, false);
|
||||
if (len <= 1 || len != dLen)
|
||||
throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String descriptorString() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@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(dropFirstAndLastChar(descriptor)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ClassDesc constant = (ClassDesc) o;
|
||||
return descriptor.equals(constant.descriptorString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return descriptor.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ClassDesc[%s]", displayName());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue