elementDecoder) {
- int length = buf.getUVInt();
- T[] result = (T[]) Array.newInstance(elementType, length);
- for (int i = 0; i < length; ++i) {
- result[i] = elementDecoder.get();
- }
- return result;
- }
-
- private static byte[] decodeByteArray(UnsafeArrayTypeReader buf) {
- int length = buf.getUVInt();
- byte[] result = new byte[length];
- for (int i = 0; i < length; ++i) {
- result[i] = (byte) buf.getS1();
- }
- return result;
- }
-
- private static ReflectParameterDescriptor decodeReflectParameter(UnsafeArrayTypeReader buf, CodeInfo info) {
- String name = decodeName(buf, info);
- int modifiers = buf.getS4();
- return new ReflectParameterDescriptor(name, modifiers);
- }
-
- public static class ReflectParameterDescriptor {
- private final String name;
- private final int modifiers;
-
- public ReflectParameterDescriptor(String name, int modifiers) {
- this.name = name;
- this.modifiers = modifiers;
- }
-
- public String getName() {
- return name;
- }
-
- public int getModifiers() {
- return modifiers;
- }
- }
-}
diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java
new file mode 100644
index 000000000000..2d25bb594e28
--- /dev/null
+++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2021, 2021, 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 com.oracle.svm.reflect.target;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.function.Function;
+
+import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+import org.graalvm.nativeimage.ImageSingletons;
+
+import com.oracle.svm.core.SubstrateUtil;
+import com.oracle.svm.core.c.NonmovableArrays;
+import com.oracle.svm.core.code.CodeInfo;
+import com.oracle.svm.core.code.CodeInfoAccess;
+import com.oracle.svm.core.code.CodeInfoTable;
+import com.oracle.svm.core.hub.DynamicHub;
+import com.oracle.svm.core.reflect.ReflectionMetadataDecoder;
+import com.oracle.svm.core.reflect.Target_java_lang_reflect_RecordComponent;
+import com.oracle.svm.core.util.ByteArrayReader;
+import com.oracle.svm.reflect.hosted.ReflectionMetadataEncoderImpl;
+
+/**
+ * This class performs the parsing of reflection metadata at runtime. The encoding formats are
+ * specified as comments above each parsing method.
+ *
+ * See {@link ReflectionMetadataEncoderImpl} for details about the emission of the metadata.
+ */
+public class ReflectionMetadataDecoderImpl implements ReflectionMetadataDecoder {
+ public static final int NO_METHOD_METADATA = -1;
+ public static final int NULL_OBJECT = -1;
+ public static final int COMPLETE_FLAG_INDEX = 31;
+ public static final int COMPLETE_FLAG_MASK = 1 << COMPLETE_FLAG_INDEX;
+ public static final int IN_HEAP_FLAG_INDEX = 30;
+ public static final int IN_HEAP_FLAG_MASK = 1 << IN_HEAP_FLAG_INDEX;
+ public static final int HIDING_FLAG_INDEX = 29;
+ public static final int HIDING_FLAG_MASK = 1 << HIDING_FLAG_INDEX;
+
+ static byte[] getEncoding() {
+ return ImageSingletons.lookup(ReflectionMetadataEncoding.class).getEncoding();
+ }
+
+ /**
+ * Fields encoding.
+ *
+ *
+ * FieldMetadata[] fields
+ *
+ */
+ @Override
+ public Field[] parseFields(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Field.class, (i) -> decodeField(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly));
+ }
+
+ /**
+ * Methods encoding.
+ *
+ *
+ * MethodMetadata[] methods
+ *
+ */
+ @Override
+ public Method[] parseMethods(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Method.class, (i) -> decodeMethod(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly));
+ }
+
+ /**
+ * Constructors encoding.
+ *
+ *
+ * ConstructorMetadata[] constructors
+ *
+ */
+ @Override
+ public Constructor>[] parseConstructors(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Constructor.class, (i) -> decodeConstructor(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly));
+ }
+
+ /**
+ * Inner classes encoding.
+ *
+ *
+ * ClassIndex[] innerClasses
+ *
+ */
+ @Override
+ public Class>[] parseClasses(int index) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Class.class, (i) -> decodeType(reader, codeInfo));
+ }
+
+ /**
+ * Record components encoding.
+ *
+ *
+ * RecordComponentMetadata[] recordComponents
+ *
+ */
+ @Override
+ public Target_java_lang_reflect_RecordComponent[] parseRecordComponents(DynamicHub declaringType, int index) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Target_java_lang_reflect_RecordComponent.class, (i) -> decodeRecordComponent(reader, codeInfo, DynamicHub.toClass(declaringType)));
+ }
+
+ /**
+ * Parameters encoding for executables.
+ *
+ *
+ * ParameterMetadata[] parameters
+ *
+ */
+ @Override
+ public Parameter[] parseReflectParameters(Executable executable, byte[] encoding) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ return decodeArray(reader, Parameter.class, (i) -> decodeReflectParameter(reader, codeInfo, executable, i));
+ }
+
+ /**
+ * Class enclosing method information. {@link Class#getEnclosingMethod()}
+ *
+ *
+ * EnclosingMethodInfo {
+ * ClassIndex declaringClass
+ * StringIndex name
+ * StringIndex descriptor
+ * }
+ *
+ */
+ @Override
+ public Object[] parseEnclosingMethod(int index) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo();
+ Class> declaringClass = decodeType(reader, codeInfo);
+ String name = decodeName(reader, codeInfo);
+ String descriptor = decodeName(reader, codeInfo);
+ return new Object[]{declaringClass, name, descriptor};
+ }
+
+ @Override
+ public byte[] parseByteArray(int index) {
+ UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess());
+ return decodeByteArray(reader);
+ }
+
+ @Override
+ public boolean isHidingMethod(int modifiers) {
+ return (modifiers & HIDING_FLAG_MASK) != 0;
+ }
+
+ @Override
+ public long getMetadataByteLength() {
+ return ImageSingletons.lookup(ReflectionMetadataEncoding.class).getEncoding().length;
+ }
+
+ /**
+ *
+ * Complete field encoding.
+ *
+ *
+ * CompleteFieldMetadata : FieldMetadata {
+ * int modifiers (including COMPLETE flag)
+ * StringIndex name
+ * ClassIndex type
+ * boolean trustedFinal (only on JDK 17 and later)
+ * StringIndex signature
+ * byte[] annotationsEncoding
+ * byte[] typeAnnotationsEncoding
+ * int offset
+ * StringIndex deletedReason
+ * }
+ *
+ *
+ * Heap field encoding.
+ *
+ *
+ * HeapFieldMetadata : FieldMetadata {
+ * int modifiers (including IN_HEAP flag)
+ * ObjectIndex fieldObject
+ * }
+ *
+ *
+ * Partial field encoding.
+ *
+ *
+ * PartialFieldMetadata : FieldMetadata {
+ * int modifiers
+ * StringIndex name
+ * }
+ *
+ */
+ private static Field decodeField(UnsafeArrayTypeReader buf, CodeInfo info, Class> declaringClass, boolean publicOnly, boolean reflectOnly) {
+ int modifiers = buf.getUVInt();
+ boolean inHeap = (modifiers & IN_HEAP_FLAG_MASK) != 0;
+ if (inHeap) {
+ Field field = (Field) decodeObject(buf, info);
+ if (publicOnly && !Modifier.isPublic(field.getModifiers())) {
+ return null;
+ }
+ return field;
+ }
+ boolean complete = (modifiers & COMPLETE_FLAG_MASK) != 0;
+ modifiers &= ~COMPLETE_FLAG_MASK;
+
+ String name = decodeName(buf, info);
+ if (!complete) {
+ if (reflectOnly) {
+ return null;
+ }
+ Target_java_lang_reflect_Field field = new Target_java_lang_reflect_Field();
+ if (JavaVersionUtil.JAVA_SPEC >= 17) {
+ field.constructorJDK17OrLater(declaringClass, name, null, modifiers, false, -1, null, null);
+ } else {
+ field.constructorJDK11OrEarlier(declaringClass, name, null, modifiers, -1, null, null);
+ }
+ return SubstrateUtil.cast(field, Field.class);
+ }
+ Class> type = decodeType(buf, info);
+ boolean trustedFinal = (JavaVersionUtil.JAVA_SPEC >= 17) ? buf.getU1() == 1 : false;
+ String signature = decodeName(buf, info);
+ byte[] annotations = decodeByteArray(buf);
+ byte[] typeAnnotations = decodeByteArray(buf);
+ int offset = buf.getSVInt();
+ String deletedReason = decodeName(buf, info);
+ if (publicOnly && !Modifier.isPublic(modifiers)) {
+ return null;
+ }
+
+ Target_java_lang_reflect_Field field = new Target_java_lang_reflect_Field();
+ if (JavaVersionUtil.JAVA_SPEC >= 17) {
+ field.constructorJDK17OrLater(declaringClass, name, type, modifiers, trustedFinal, -1, signature, annotations);
+ } else {
+ field.constructorJDK11OrEarlier(declaringClass, name, type, modifiers, -1, signature, annotations);
+ }
+ field.offset = offset;
+ field.deletedReason = deletedReason;
+ SubstrateUtil.cast(field, Target_java_lang_reflect_AccessibleObject.class).typeAnnotations = typeAnnotations;
+ return SubstrateUtil.cast(field, Field.class);
+ }
+
+ /**
+ * Complete method encoding.
+ *
+ *
+ * CompleteMethodMetadata : MethodMetadata {
+ * int modifiers (including COMPLETE flag)
+ * StringIndex name
+ * ClassIndex[] parameterTypes
+ * ClassIndex returnType
+ * StringIndex signature
+ * byte[] annotationsEncoding
+ * byte[] parameterAnnotationsEncoding
+ * byte[] annotationDefaultEncoding (annotation methods only)
+ * byte[] typeAnnotationsEncoding
+ * byte[] reflectParametersEncoding ({@link #decodeReflectParameter(UnsafeArrayTypeReader, CodeInfo, Executable, int)})
+ * ObjectIndex accessor (null if registered as queried only)
+ * }
+ *
+ *
+ * Heap method encoding.
+ *
+ *
+ * HeapMethodMetadata : MethodMetadata {
+ * int modifiers (including IN_HEAP flag)
+ * ObjectIndex methodObject
+ * }
+ *
+ *
+ * Partial method encoding.
+ *
+ *
+ * PartialMethodMetadata : MethodMetadata {
+ * int modifiers
+ * StringIndex name
+ * ClassIndex[] parameterTypes
+ * ClassIndex returnType
+ * }
+ *
+ */
+ private static Method decodeMethod(UnsafeArrayTypeReader buf, CodeInfo info, Class> declaringClass, boolean publicOnly, boolean reflectOnly) {
+ return (Method) decodeExecutable(buf, info, declaringClass, publicOnly, reflectOnly, true);
+ }
+
+ /**
+ * Complete constructor encoding.
+ *
+ *
+ * CompleteConstructorMetadata : ConstructorMetadata {
+ * int modifiers (including COMPLETE flag)
+ * ClassIndex[] parameterTypes
+ * StringIndex signature
+ * byte[] annotationsEncoding
+ * byte[] parameterAnnotationsEncoding
+ * byte[] typeAnnotationsEncoding
+ * byte[] reflectParametersEncoding ({@link #parseReflectParameters(Executable, byte[])})
+ * ObjectIndex accessor (null if registered as queried only)
+ * }
+ *
+ *
+ * Heap constructor encoding.
+ *
+ *
+ * HeapConstructorMetadata : ConstructorMetadata {
+ * int modifiers (including IN_HEAP flag)
+ * ObjectIndex constructorObject
+ * }
+ *
+ *
+ * Partial constructor encoding.
+ *
+ *
+ * PartialConstructorMetadata : ConstructorMetadata {
+ * int modifiers
+ * ClassIndex[] parameterTypes
+ * }
+ *
+ */
+ private static Constructor> decodeConstructor(UnsafeArrayTypeReader buf, CodeInfo info, Class> declaringClass, boolean publicOnly, boolean reflectOnly) {
+ return (Constructor>) decodeExecutable(buf, info, declaringClass, publicOnly, reflectOnly, false);
+ }
+
+ private static Executable decodeExecutable(UnsafeArrayTypeReader buf, CodeInfo info, Class> declaringClass, boolean publicOnly, boolean reflectOnly, boolean isMethod) {
+ int modifiers = buf.getUVInt();
+ boolean inHeap = (modifiers & IN_HEAP_FLAG_MASK) != 0;
+ if (inHeap) {
+ Executable executable = (Executable) decodeObject(buf, info);
+ if (publicOnly && !Modifier.isPublic(executable.getModifiers())) {
+ return null;
+ }
+ return executable;
+ }
+ boolean complete = (modifiers & COMPLETE_FLAG_MASK) != 0;
+ boolean hiding = (modifiers & HIDING_FLAG_MASK) != 0;
+ assert !(complete && hiding);
+ modifiers &= ~COMPLETE_FLAG_MASK;
+
+ String name = isMethod ? decodeName(buf, info) : null;
+ Class>[] parameterTypes = decodeArray(buf, Class.class, (i) -> decodeType(buf, info));
+ Class> returnType = isMethod ? decodeType(buf, info) : null;
+ if (!complete) {
+ if (reflectOnly != hiding) {
+ /*
+ * When querying for reflection methods, we want the hiding methods but not the
+ * reachable methods. When querying for reachable methods, we want the reachable
+ * methods but not the hiding methods.
+ */
+ return null;
+ }
+ if (isMethod) {
+ Target_java_lang_reflect_Method method = new Target_java_lang_reflect_Method();
+ method.constructor(declaringClass, name, parameterTypes, returnType, null, modifiers, -1, null, null, null, null);
+ return SubstrateUtil.cast(method, Executable.class);
+ } else {
+ Target_java_lang_reflect_Constructor constructor = new Target_java_lang_reflect_Constructor();
+ constructor.constructor(declaringClass, parameterTypes, null, modifiers, -1, null, null, null);
+ return SubstrateUtil.cast(constructor, Executable.class);
+ }
+ }
+ Class>[] exceptionTypes = decodeArray(buf, Class.class, (i) -> decodeType(buf, info));
+ String signature = decodeName(buf, info);
+ byte[] annotations = decodeByteArray(buf);
+ byte[] parameterAnnotations = decodeByteArray(buf);
+ byte[] annotationDefault = isMethod && declaringClass.isAnnotation() ? decodeByteArray(buf) : null;
+ byte[] typeAnnotations = decodeByteArray(buf);
+ byte[] reflectParameters = decodeByteArray(buf);
+ Object accessor = decodeObject(buf, info);
+ if (publicOnly && !Modifier.isPublic(modifiers)) {
+ return null;
+ }
+
+ Target_java_lang_reflect_Executable executable;
+ if (isMethod) {
+ Target_java_lang_reflect_Method method = new Target_java_lang_reflect_Method();
+ method.constructor(declaringClass, name, parameterTypes, returnType, exceptionTypes, modifiers, -1, signature, annotations, parameterAnnotations, annotationDefault);
+ method.methodAccessor = (Target_jdk_internal_reflect_MethodAccessor) accessor;
+ executable = SubstrateUtil.cast(method, Target_java_lang_reflect_Executable.class);
+ } else {
+ Target_java_lang_reflect_Constructor constructor = new Target_java_lang_reflect_Constructor();
+ constructor.constructor(declaringClass, parameterTypes, exceptionTypes, modifiers, -1, signature, annotations, parameterAnnotations);
+ constructor.constructorAccessor = (Target_jdk_internal_reflect_ConstructorAccessor) accessor;
+ executable = SubstrateUtil.cast(constructor, Target_java_lang_reflect_Executable.class);
+ }
+ executable.rawParameters = reflectParameters;
+ SubstrateUtil.cast(executable, Target_java_lang_reflect_AccessibleObject.class).typeAnnotations = typeAnnotations;
+ return SubstrateUtil.cast(executable, Executable.class);
+ }
+
+ /**
+ * Record component encoding.
+ *
+ *
+ * RecordComponentMetadata {
+ * StringIndex name
+ * ClassIndex type
+ * StringIndex signature
+ * ObjectIndex accessor
+ * byte[] annotations
+ * byte[] typeAnnotations
+ * }
+ *
+ */
+ private static Target_java_lang_reflect_RecordComponent decodeRecordComponent(UnsafeArrayTypeReader buf, CodeInfo info, Class> declaringClass) {
+ String name = decodeName(buf, info);
+ Class> type = decodeType(buf, info);
+ String signature = decodeName(buf, info);
+ Method accessor = (Method) decodeObject(buf, info);
+ byte[] annotations = decodeByteArray(buf);
+ byte[] typeAnnotations = decodeByteArray(buf);
+
+ Target_java_lang_reflect_RecordComponent recordComponent = new Target_java_lang_reflect_RecordComponent();
+ recordComponent.clazz = declaringClass;
+ recordComponent.name = name;
+ recordComponent.type = type;
+ recordComponent.signature = signature;
+ recordComponent.accessor = accessor;
+ recordComponent.annotations = annotations;
+ recordComponent.typeAnnotations = typeAnnotations;
+ return recordComponent;
+ }
+
+ /**
+ * Parameter encoding for executables.
+ *
+ *
+ * ParameterMetadata {
+ * StringIndex name
+ * int modifiers
+ * }
+ *
+ */
+
+ private static Parameter decodeReflectParameter(UnsafeArrayTypeReader buf, CodeInfo info, Executable executable, int i) {
+ String name = decodeName(buf, info);
+ int modifiers = buf.getUVInt();
+
+ Target_java_lang_reflect_Parameter parameter = new Target_java_lang_reflect_Parameter();
+ parameter.constructor(name, modifiers, executable, i);
+ return SubstrateUtil.cast(parameter, Parameter.class);
+ }
+
+ /**
+ * Types are encoded as indices in the frame info source classes array.
+ */
+ private static Class> decodeType(UnsafeArrayTypeReader buf, CodeInfo info) {
+ int classIndex = buf.getSVInt();
+ if (classIndex == NO_METHOD_METADATA) {
+ return null;
+ }
+ return NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), classIndex);
+ }
+
+ /**
+ * Names are encoded as indices in the frame info source method names array.
+ */
+ private static String decodeName(UnsafeArrayTypeReader buf, CodeInfo info) {
+ int nameIndex = buf.getSVInt();
+ String name = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), nameIndex);
+ /* Interning the string to ensure JDK8 method search succeeds */
+ return name == null ? null : name.intern();
+ }
+
+ /**
+ * Objects (method accessors and reflection objects in the heap) are encoded as indices in the
+ * frame info object constants array.
+ */
+ private static Object decodeObject(UnsafeArrayTypeReader buf, CodeInfo info) {
+ int objectIndex = buf.getSVInt();
+ if (objectIndex == NULL_OBJECT) {
+ return null;
+ }
+ return NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoObjectConstants(info), objectIndex);
+ }
+
+ /**
+ * Arrays are encoded by their length followed by the elements encoded one after the other.
+ */
+ @SuppressWarnings("unchecked")
+ private static T[] decodeArray(UnsafeArrayTypeReader buf, Class elementType, Function elementDecoder) {
+ int length = buf.getUVInt();
+ T[] result = (T[]) Array.newInstance(elementType, length);
+ int valueCount = 0;
+ for (int i = 0; i < length; ++i) {
+ T element = elementDecoder.apply(i);
+ if (element != null) {
+ result[valueCount++] = element;
+ }
+ }
+ return Arrays.copyOf(result, valueCount);
+ }
+
+ private static byte[] decodeByteArray(UnsafeArrayTypeReader buf) {
+ int length = buf.getUVInt();
+ if (length == NO_DATA) {
+ return null;
+ }
+ byte[] result = new byte[length];
+ for (int i = 0; i < length; ++i) {
+ result[i] = (byte) buf.getS1();
+ }
+ return result;
+ }
+}
diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataEncoding.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java
similarity index 67%
rename from substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataEncoding.java
rename to substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java
index f5945a6e2989..fc33ab2c2b53 100644
--- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataEncoding.java
+++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2022, 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
@@ -29,25 +29,15 @@
import com.oracle.svm.core.annotate.UnknownObjectField;
-public class MethodMetadataEncoding {
- @UnknownObjectField(types = {byte[].class}) private byte[] methodsEncoding;
- @UnknownObjectField(types = {byte[].class}) private byte[] indexEncoding;
+public class ReflectionMetadataEncoding {
+ @UnknownObjectField(types = {byte[].class}) private byte[] encoding;
- public byte[] getMethodsEncoding() {
- return methodsEncoding;
+ public byte[] getEncoding() {
+ return encoding;
}
@Platforms(Platform.HOSTED_ONLY.class)
- public void setMethodsEncoding(byte[] methodsEncoding) {
- this.methodsEncoding = methodsEncoding;
- }
-
- public byte[] getIndexEncoding() {
- return indexEncoding;
- }
-
- @Platforms(Platform.HOSTED_ONLY.class)
- public void setIndexEncoding(byte[] indexEncoding) {
- this.indexEncoding = indexEncoding;
+ public void setEncoding(byte[] encoding) {
+ this.encoding = encoding;
}
}
diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java
index e988e4f00540..df50222f2c57 100644
--- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java
+++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java
@@ -26,12 +26,20 @@
import java.lang.reflect.AccessibleObject;
+import org.graalvm.nativeimage.ImageSingletons;
+
import com.oracle.svm.core.annotate.Alias;
+import com.oracle.svm.core.annotate.Inject;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
+import com.oracle.svm.core.annotate.UnknownObjectField;
import com.oracle.svm.core.jdk.JDK11OrEarlier;
import com.oracle.svm.core.jdk.JDK17OrLater;
+import com.oracle.svm.hosted.image.NativeImageCodeCache;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
@TargetClass(value = AccessibleObject.class)
public final class Target_java_lang_reflect_AccessibleObject {
@@ -46,6 +54,22 @@ public final class Target_java_lang_reflect_AccessibleObject {
@TargetElement(onlyWith = JDK17OrLater.class) //
volatile Object accessCheckCache;
- @Alias //
- native Target_java_lang_reflect_AccessibleObject getRoot();
+ @Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = TypeAnnotationsComputer.class) //
+ @UnknownObjectField(types = {byte[].class}) byte[] typeAnnotations;
+
+ @Alias
+ native AccessibleObject getRoot();
+
+ static class TypeAnnotationsComputer implements RecomputeFieldValue.CustomFieldValueComputer {
+
+ @Override
+ public RecomputeFieldValue.ValueAvailability valueAvailability() {
+ return RecomputeFieldValue.ValueAvailability.AfterCompilation;
+ }
+
+ @Override
+ public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
+ return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getTypeAnnotationsEncoding((AccessibleObject) receiver);
+ }
+ }
}
diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java
index 4527c1b7ac15..2fa6e30e8bc9 100644
--- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java
+++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java
@@ -26,59 +26,43 @@
import static com.oracle.svm.core.annotate.TargetElement.CONSTRUCTOR_NAME;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
+import java.lang.reflect.Executable;
+
+import org.graalvm.nativeimage.ImageSingletons;
-import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
-import com.oracle.svm.core.annotate.Inject;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
-import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer;
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.annotate.TargetElement;
+import com.oracle.svm.core.annotate.UnknownObjectField;
import com.oracle.svm.core.util.VMError;
+import com.oracle.svm.hosted.image.NativeImageCodeCache;
import com.oracle.svm.reflect.hosted.ExecutableAccessorComputer;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
-import sun.reflect.annotation.TypeAnnotation;
-import sun.reflect.generics.repository.ConstructorRepository;
@TargetClass(value = Constructor.class)
public final class Target_java_lang_reflect_Constructor {
- @Alias ConstructorRepository genericInfo;
-
- @Alias private Class>[] parameterTypes;
-
- @Alias @RecomputeFieldValue(kind = Kind.Reset)//
- private byte[] annotations;
+ @Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotationsComputer.class)//
+ @UnknownObjectField(types = {byte[].class}) byte[] annotations;
- @Alias @RecomputeFieldValue(kind = Kind.Reset)//
- private byte[] parameterAnnotations;
+ @Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = ParameterAnnotationsComputer.class)//
+ @UnknownObjectField(types = {byte[].class}) byte[] parameterAnnotations;
@Alias //
@RecomputeFieldValue(kind = Kind.Custom, declClass = ExecutableAccessorComputer.class) //
Target_jdk_internal_reflect_ConstructorAccessor constructorAccessor;
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = ConstructorAnnotatedReceiverTypeComputer.class) //
- AnnotatedType annotatedReceiverType;
-
@Alias
@TargetElement(name = CONSTRUCTOR_NAME)
@SuppressWarnings("hiding")
- public native void constructor(Class> declaringClass,
- Class>[] parameterTypes,
- Class>[] checkedExceptions,
- int modifiers,
- int slot,
- String signature,
- byte[] annotations,
+ public native void constructor(Class> declaringClass, Class>[] parameterTypes, Class>[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations,
byte[] parameterAnnotations);
@Alias
@@ -92,73 +76,29 @@ Target_jdk_internal_reflect_ConstructorAccessor acquireConstructorAccessor() {
return constructorAccessor;
}
- @Alias //
- public native Class> getDeclaringClass();
-
- @Substitute
- public Annotation[][] getParameterAnnotations() {
- Target_java_lang_reflect_Executable self = SubstrateUtil.cast(this, Target_java_lang_reflect_Executable.class);
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(self);
- if (holder.parameterAnnotations != null) {
- return holder.parameterAnnotations;
- }
- return self.sharedGetParameterAnnotations(parameterTypes, parameterAnnotations);
- }
-
- @Substitute
- public AnnotatedType getAnnotatedReceiverType() {
- Target_java_lang_reflect_Constructor holder = ReflectionHelper.getHolder(this);
- if (holder.annotatedReceiverType != null) {
- return holder.annotatedReceiverType;
- }
- Class> thisDeclClass = getDeclaringClass();
- Class> enclosingClass = thisDeclClass.getEnclosingClass();
-
- if (enclosingClass == null) {
- // A Constructor for a top-level class
- return null;
- }
-
- Class> outerDeclaringClass = thisDeclClass.getDeclaringClass();
- if (outerDeclaringClass == null) {
- // A constructor for a local or anonymous class
- return null;
- }
+ static class AnnotationsComputer implements RecomputeFieldValue.CustomFieldValueComputer {
- // Either static nested or inner class
- if (Modifier.isStatic(thisDeclClass.getModifiers())) {
- // static nested
- return null;
+ @Override
+ public RecomputeFieldValue.ValueAvailability valueAvailability() {
+ return RecomputeFieldValue.ValueAvailability.AfterCompilation;
}
- if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- // A Constructor for an inner class
- return Target_sun_reflect_annotation_TypeAnnotationParser.buildAnnotatedType(SubstrateUtil.cast(holder, Target_java_lang_reflect_Executable.class).typeAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- SubstrateUtil.cast(this, AnnotatedElement.class),
- thisDeclClass,
- enclosingClass,
- TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
+ @Override
+ public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
+ return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver);
}
- throw VMError.shouldNotReachHere();
}
- /**
- * The Constructor.annotatedReceiverType computation is needed, even though there is a similar
- * computation for Executable.annotatedReceiverType, because the Constructor class overrides
- * Executable.getAnnotatedReceiverType().
- */
- public static final class ConstructorAnnotatedReceiverTypeComputer implements CustomFieldValueComputer {
+ static class ParameterAnnotationsComputer implements RecomputeFieldValue.CustomFieldValueComputer {
+
@Override
public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
+ return RecomputeFieldValue.ValueAvailability.AfterCompilation;
}
@Override
public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Constructor> constructor = (Constructor>) receiver;
- return constructor.getAnnotatedReceiverType();
+ return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getParameterAnnotationsEncoding((Executable) receiver);
}
}
-
}
diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java
index f56e3a90520f..72813c6aef51 100644
--- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java
+++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java
@@ -25,304 +25,61 @@
package com.oracle.svm.reflect.target;
import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Executable;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
+import java.lang.reflect.Parameter;
import java.util.Map;
-import java.util.function.Supplier;
+
+import org.graalvm.nativeimage.ImageSingletons;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Inject;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
-import com.oracle.svm.core.annotate.RecomputeFieldValue.CustomFieldValueComputer;
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
-import com.oracle.svm.core.util.VMError;
-import com.oracle.svm.hosted.LinkAtBuildTimeSupport;
-import com.oracle.svm.reflect.hosted.ReflectionObjectReplacer;
+import com.oracle.svm.core.annotate.UnknownObjectField;
+import com.oracle.svm.core.reflect.ReflectionMetadataDecoder;
+import com.oracle.svm.hosted.image.NativeImageCodeCache;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
-import sun.reflect.annotation.TypeAnnotation;
@TargetClass(value = Executable.class)
public final class Target_java_lang_reflect_Executable {
- /**
- * The parameters field doesn't need a value recomputation. Its value is pre-loaded in the
- * {@link ReflectionObjectReplacer}.
- */
- @Alias //
- Target_java_lang_reflect_Parameter[] parameters;
-
- @Alias //
- boolean hasRealParameterData;
+ @Alias @RecomputeFieldValue(kind = Kind.Reset)//
+ Parameter[] parameters;
- /**
- * The declaredAnnotations field doesn't need a value recomputation. Its value is pre-loaded in
- * the {@link ReflectionObjectReplacer}.
- */
- @Alias //
+ @Alias @RecomputeFieldValue(kind = Kind.Reset)//
Map, Annotation> declaredAnnotations;
- @Inject @RecomputeFieldValue(kind = Kind.Reset) //
- byte[] typeAnnotations;
-
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = ParameterAnnotationsComputer.class) //
- Annotation[][] parameterAnnotations;
-
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotatedReceiverTypeComputer.class) //
- Object annotatedReceiverType;
-
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotatedParameterTypesComputer.class) //
- Object[] annotatedParameterTypes;
-
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotatedReturnTypeComputer.class) //
- Object annotatedReturnType;
-
- @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotatedExceptionTypesComputer.class) //
- Object[] annotatedExceptionTypes;
-
- @Alias //
- public native int getModifiers();
-
- @Alias //
- native byte[] getAnnotationBytes();
-
- @Alias //
- public native Class> getDeclaringClass();
-
- @Alias //
- native Type[] getAllGenericParameterTypes();
-
- @Alias //
- public native Type[] getGenericExceptionTypes();
-
- @Alias //
- private native Target_java_lang_reflect_Parameter[] synthesizeAllParams();
-
- @Substitute
- private Target_java_lang_reflect_Parameter[] privateGetParameters() {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- if (holder.parameters != null) {
- return holder.parameters;
- } else if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- assert !hasRealParameterData;
- holder.parameters = synthesizeAllParams();
- return holder.parameters;
- }
- throw VMError.shouldNotReachHere();
- }
+ @Inject @RecomputeFieldValue(kind = Kind.Custom, declClass = RawParametersComputer.class)//
+ @UnknownObjectField(types = {byte[].class}) byte[] rawParameters;
@Substitute
- Map, Annotation> declaredAnnotations() {
- Map, Annotation> declAnnos;
- if ((declAnnos = declaredAnnotations) == null) {
- if (!MethodMetadataDecoderImpl.hasQueriedMethods()) {
- throw VMError.shouldNotReachHere();
- }
- synchronized (this) {
- if ((declAnnos = declaredAnnotations) == null) {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- declAnnos = Target_sun_reflect_annotation_AnnotationParser.parseAnnotations(
- holder.getAnnotationBytes(),
- new Target_jdk_internal_reflect_ConstantPool(),
- holder.getDeclaringClass());
- declaredAnnotations = declAnnos;
- }
- }
- }
- return declAnnos;
- }
-
- @Alias
- native Annotation[][] sharedGetParameterAnnotations(Class>[] parameterTypes, byte[] annotations);
-
- @Substitute
- @SuppressWarnings({"unused", "hiding", "static-method"})
- Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) {
- if (!MethodMetadataDecoderImpl.hasQueriedMethods()) {
- throw VMError.shouldNotReachHere();
- }
- return Target_sun_reflect_annotation_AnnotationParser.parseParameterAnnotations(
- parameterAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- getDeclaringClass());
- }
-
- @Substitute
- public AnnotatedType getAnnotatedReceiverType() {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- if (holder.annotatedReceiverType != null) {
- return (AnnotatedType) AnnotatedTypeEncoder.decodeAnnotationTypes(holder.annotatedReceiverType);
- }
- if (Modifier.isStatic(this.getModifiers())) {
+ private Parameter[] getParameters0() {
+ if (rawParameters == null) {
return null;
}
- if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- AnnotatedType annotatedRecvType = Target_sun_reflect_annotation_TypeAnnotationParser.buildAnnotatedType(typeAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- SubstrateUtil.cast(this, AnnotatedElement.class),
- getDeclaringClass(),
- getDeclaringClass(),
- TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
- holder.annotatedReceiverType = annotatedRecvType;
- return annotatedRecvType;
- }
- throw VMError.shouldNotReachHere();
+ return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseReflectParameters(SubstrateUtil.cast(this, Executable.class), rawParameters);
}
@Substitute
- public AnnotatedType[] getAnnotatedParameterTypes() {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- if (holder.annotatedParameterTypes != null) {
- return (AnnotatedType[]) AnnotatedTypeEncoder.decodeAnnotationTypes(holder.annotatedParameterTypes);
- } else if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- AnnotatedType[] annotatedParamTypes = Target_sun_reflect_annotation_TypeAnnotationParser.buildAnnotatedTypes(typeAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- SubstrateUtil.cast(this, AnnotatedElement.class),
- getDeclaringClass(),
- getAllGenericParameterTypes(),
- TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
- holder.annotatedParameterTypes = annotatedParamTypes;
- return annotatedParamTypes;
- }
- throw VMError.shouldNotReachHere();
+ byte[] getTypeAnnotationBytes0() {
+ return SubstrateUtil.cast(this, Target_java_lang_reflect_AccessibleObject.class).typeAnnotations;
}
- @Substitute
- public AnnotatedType getAnnotatedReturnType0(@SuppressWarnings("unused") Type returnType) {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- if (holder.annotatedReturnType != null) {
- return (AnnotatedType) AnnotatedTypeEncoder.decodeAnnotationTypes(holder.annotatedReturnType);
- } else if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- AnnotatedType annotatedRetType = Target_sun_reflect_annotation_TypeAnnotationParser.buildAnnotatedType(typeAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- SubstrateUtil.cast(this, AnnotatedElement.class),
- getDeclaringClass(),
- returnType,
- TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN);
- holder.annotatedReturnType = annotatedRetType;
- return annotatedRetType;
- }
- throw VMError.shouldNotReachHere();
- }
+ static class RawParametersComputer implements RecomputeFieldValue.CustomFieldValueComputer {
- @Substitute
- public AnnotatedType[] getAnnotatedExceptionTypes() {
- Target_java_lang_reflect_Executable holder = ReflectionHelper.getHolder(this);
- if (holder.annotatedExceptionTypes != null) {
- return (AnnotatedType[]) AnnotatedTypeEncoder.decodeAnnotationTypes(holder.annotatedExceptionTypes);
- } else if (MethodMetadataDecoderImpl.hasQueriedMethods()) {
- AnnotatedType[] annotatedExcTypes = Target_sun_reflect_annotation_TypeAnnotationParser.buildAnnotatedTypes(typeAnnotations,
- new Target_jdk_internal_reflect_ConstantPool(),
- SubstrateUtil.cast(this, AnnotatedElement.class),
- getDeclaringClass(),
- getGenericExceptionTypes(),
- TypeAnnotation.TypeAnnotationTarget.THROWS);
- holder.annotatedExceptionTypes = annotatedExcTypes;
- return annotatedExcTypes;
- }
- throw VMError.shouldNotReachHere();
- }
-
- public static final class ParameterAnnotationsComputer implements CustomFieldValueComputer {
@Override
public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
+ return RecomputeFieldValue.ValueAvailability.AfterCompilation;
}
@Override
public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Executable executable = (Executable) receiver;
- return executable.getParameterAnnotations();
- }
- }
-
- public static final class AnnotatedReceiverTypeComputer implements CustomFieldValueComputer {
- @Override
- public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
- }
-
- @Override
- public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Executable executable = (Executable) receiver;
- return AnnotatedTypeEncoder.encodeAnnotationTypes(executable::getAnnotatedReceiverType, executable);
- }
- }
-
- public static final class AnnotatedParameterTypesComputer implements CustomFieldValueComputer {
- @Override
- public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
- }
-
- @Override
- public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Executable executable = (Executable) receiver;
- return AnnotatedTypeEncoder.encodeAnnotationTypes(executable::getAnnotatedParameterTypes, executable);
- }
- }
-
- public static final class AnnotatedReturnTypeComputer implements CustomFieldValueComputer {
- @Override
- public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
- }
-
- @Override
- public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Executable executable = (Executable) receiver;
- return AnnotatedTypeEncoder.encodeAnnotationTypes(executable::getAnnotatedReturnType, executable);
- }
- }
-
- public static final class AnnotatedExceptionTypesComputer implements CustomFieldValueComputer {
- @Override
- public RecomputeFieldValue.ValueAvailability valueAvailability() {
- return RecomputeFieldValue.ValueAvailability.BeforeAnalysis;
- }
-
- @Override
- public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) {
- Executable executable = (Executable) receiver;
- return AnnotatedTypeEncoder.encodeAnnotationTypes(executable::getAnnotatedExceptionTypes, executable);
- }
- }
-
- private static final class AnnotatedTypeEncoder {
- static Object encodeAnnotationTypes(Supplier