Предпосылка представляет собой сложный сценарий начальной загрузки экспериментального компилятора, где компилятор необходимо выполнить некоторый код, который был скомпилирован ранее на том же этапе.
Существует интерфейс, который расширяет параметризованный интерфейс и связывает аргумент типа:
Код: Выделить всё
interface Reals extends Provider
{
//...
}
Код: Выделить всё
@Implements("lang.Reals")
@bind interface Reals extends Provider
{
//...
}
Конфигурация Byte Buddy под капотом:
Код: Выделить всё
ByteBuddy byteBuddy = new ByteBuddy(JAVA_V9)
. with(TypeValidation.DISABLED)
. with(MethodGraph.Compiler.Default.forJVMHierarchy)
Итак, после этой длинной преамбулы, когда код выполняется для этого конкретного сценария, я получаю следующее исключение:
Код: Выделить всё
java.lang.TypeNotPresentException: Type lang.Real not present
at java.base/sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:117)
at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125)
at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
at java.base/sun.reflect.generics.visitor.Reifier.reifyTypeArguments(Reifier.java:68)
at java.base/sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:138)
at java.base/sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
at java.base/sun.reflect.generics.repository.ClassRepository.computeSuperInterfaces(ClassRepository.java:117)
at java.base/sun.reflect.generics.repository.ClassRepository.getSuperInterfaces(ClassRepository.java:95)
at java.base/java.lang.Class.getGenericInterfaces(Class.java:1211)
at net.bytebuddy.description.type.TypeList$Generic$OfLoadedInterfaceTypes$TypeProjection.resolve(TypeList.java:823)
at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection.accept(TypeDescription.java:6297)
at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithResolvedErasure.resolve(TypeDescription.java:6949)
at net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection.accept(TypeDescription.java:6297)
at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.doAnalyze(MethodGraph.java:746)
at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.analyze(MethodGraph.java:710)
at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.doAnalyze(MethodGraph.java:746)
at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default.compile(MethodGraph.java:668)
at net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$AbstractBase.compile(MethodGraph.java:519)
at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:472)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.toTypeWriter(SubclassDynamicTypeBuilder.java:212)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.toTypeWriter(SubclassDynamicTypeBuilder.java:203)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4055)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3739)
at pro.projo.internal.rcg.RuntimeCodeGenerationHandler.generateImplementation(RuntimeCodeGenerationHandler.java:208)
at pro.projo.internal.rcg.RuntimeCodeGenerationHandler.lambda$getImplementationOf$0(RuntimeCodeGenerationHandler.java:183)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1740)
at pro.projo.internal.rcg.RuntimeCodeGenerationHandler.getImplementationOf(RuntimeCodeGenerationHandler.java:183)
at pro.projo.Projo.getImplementationClass(Projo.java:496)
at pro.projo.Projo.getImplementationClass(Projo.java:468)
at natives.bootstrap.Bootstrap.bindNativeImplementation(Bootstrap.java:139)
Проблема достигает апогея, когда Byte Buddy пытается разрешить интерфейсы исходный интерфейс Reals (
Код: Выделить всё
TypeList.java:822
Код: Выделить всё
protected TypeDescription.Generic resolve() {
java.lang.reflect.Type[] type = this.type.getGenericInterfaces();
Byte Buddy с этим справляется абсолютно правильно, я не говорю, что есть здесь какая-то ошибка. Однако в рассматриваемом сценарии я хотел бы заменить этот код простым вызовом getInterfaces(), который предположительно не вызовет попытку загрузки аргумента типа Provider. Способ использования поставщика Reals является полностью универсальным, то есть он будет вызываться только с помощью методов моста, а не с помощью каких-либо методов, в которых параметр типа заменяется фактическим типом Real в качестве возвращаемого значения. тип или тип параметра (фактически будут сгенерированы только методы моста, которые будут содержать фактическую реализацию метода, а не проверку и перенаправление на метод реализации).
Вкратце: что я ищу способ настроить это поведение в Byte Buddy, чтобы я мог создавать код во время выполнения, который будет обрабатывать интерфейсы как необработанные типы и не загружать преждевременно тип Real.
Что я пробовал до сих пор (все безуспешно и приводило только ко множеству других исключений):
- Замена TypeDescription.ForLoadedType< /code> (что, по-видимому, является причиной использования отражения при разрешении типов) с помощью TypeDescription.Latent
- Используя настроенный подкласс TypeDescription.Latent, который переопределяет некоторые методы, вызвавшие другие исключения.
- Замена MethodGraph.Compiler.Default.forJVMHierarchy собственной реализацией компилятора графа методов, которая пытается обойти эту проблему.
- Реализован TypeDescription.Generic.Visitor для использования компилятором графа метода, снова пытаясь заменить часть кода по умолчанию настраиваемой альтернативной обработкой.
- Реализован TypeDescription.Generic.Visitor, который будет использоваться компилятором графа метода, снова пытаясь заменить часть кода по умолчанию настраиваемой альтернативной обработкой.
- >
Различные комбинации вышеперечисленного
Подробнее здесь: https://stackoverflow.com/questions/791 ... ameterized