Я использую Byte Buddy 1.9.0 в качестве генератора кода для языка программирования на основе Xtext, и я изо всех сил пытаюсь создать байт-код для метода, который создает экземпляр «анонимного» класса. Для всех намерений и целей я пытаюсь, чтобы Byte Buddy создал метод, эквивалентный этому:
package fxxx.test;
class DummyUser
{
DummyOperator dummy()
{
return new DummyUser$1();
}
}
Мой компилятор уже создал вложенный "анонимный" класс DummyUser$1
, но, для жизни я не могу придумать правильную последовательность инструкций Byte Buddy, чтобы создать новый объект этого класса и затем вернуть этот объект. После некоторого поиска я наткнулся на MethodCall.construct(MethodDescription)
, но мой текущий код выдает только следующее исключение:
java.lang.IllegalStateException: Cannot return void from public fxxx.test.DummyOperator fxxx.test.DummyUser_.dummy()
at net.bytebuddy.implementation.MethodCall$TerminationHandler$1.resolve(MethodCall.java:2189)
at net.bytebuddy.implementation.MethodCall.toStackManipulation(MethodCall.java:2405)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:2434)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:698)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:683)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:590)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5114)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1915)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:197)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:174)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3376)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3565)
...
Эта ошибка, кажется, довольно понятно говорит мне, что, поскольку конструктор для класса имеет <init>()V
сигнатура и технически возвращает void
это эквивалентно возвращению void
значения из метода, который должен действительно возвращать некоторый подкласс DummyOperator
. Я попытался объединить MethodCall.construct
с StackManipulation
, который дублирует вершину стека, но, поскольку TypeCreation
через байт-код new
уже запекан в MethodCall.construct
, я не имею доступа к недавно созданный экземпляр необработанного объекта. Проект еще не открыт, но я могу предоставить этот фрагмент (используя синтаксис Xtend), чтобы проиллюстрировать, что делает мой код:
val Builder<?> anonymousClass = ... // the anonymous class that has already been created
val TypeDescription declaringType = describe(anonymousClass) // basically .make.typeDescription
val MethodDescription constructor = method(declaringType, new TypeDescription.ForLoadedType(void), "<init>", #[]) // new Latent declaringType/returnType
val MethodCall construct = MethodCall.construct(constructor)
// ^^^ this value gets return as the new method's Implementation
Чего мне не хватает, чтобы метод правильно возвращал вновь созданный экземпляр?