字节预算:生成具有循环类型的类 [英] Byte-buddy: generate classes with cyclic types

查看:44
本文介绍了字节预算:生成具有循环类型的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试生成具有循环类依赖性的类,类似于此问题:

I'm trying to generate classes with a cyclic class dependency, similar to this question: Byte Buddy - Handling cyclic references in generated classes

作为一个最小的示例,我要生成的类的种类具有这样的依赖关系:

As a minimal example, the kind of classes I want to generate have dependencies like this:

//class A depends on class B, and vice-versa
final class A { B theB; }
final class B { A theA; }

上面链接中接受的答案没有为我提供足够的信息来使它起作用.这是我尝试过的:

The accepted answer in the link above did not provide enough information for me to get this to work. This is what I tried:

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.jar.asm.Opcodes;

public class ByteBuddyHello {

    public static void main(String[] args) {
        try {
            final ByteBuddy bb = new ByteBuddy();
            final TypeDescription.Latent typeDescrA = new TypeDescription.Latent("A", 0, null, null);
            final TypeDescription.Latent typeDescrB = new TypeDescription.Latent("B", 0, null, null);
            final DynamicType.Unloaded<Object> madeA = bb
                    .subclass(Object.class)
                    .name("A")
                    .defineField("theB", typeDescrB, Opcodes.ACC_PUBLIC)
                    .make(); // exception thrown here!
            final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
                    .name("B")
                    .defineField("theA", typeDescrA, Opcodes.ACC_PUBLIC)
                    .make();

            Object a = madeA
                    .include(madeB)
                    .load(ByteBuddyHello.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                    .getLoaded().newInstance();
            System.out.println(a.toString());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

运行此命令时,在线程主" java.lang.IllegalStateException中得到 Exception:无法解析标记行中的潜在类型描述的声明类型:B类.

When I run this, I get Exception in thread "main" java.lang.IllegalStateException: Cannot resolve declared type of a latent type description: class B in the marked line.

上述参考问题的答案是确保在正确定义潜在类型之前不要加载类型",我猜测这可能是我的问题.我不知道如何定义潜在类型:-(

The answer to the referenced question above says to "Make sure that you do not load a type before defining the latent type properly", and I'm guessing that this might be my issue. I don't know how to define a latent type though :-(

Exception in thread "main" java.lang.IllegalStateException: Cannot resolve declared type of a latent type description: class B
    at net.bytebuddy.description.type.TypeDescription$Latent.getDeclaringType(TypeDescription.java:7613)
    at net.bytebuddy.description.type.TypeDescription$AbstractBase.getSegmentCount(TypeDescription.java:6833)
    at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onNonGenericType(AnnotationAppender.java:617)
    at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onNonGenericType(AnnotationAppender.java:333)
    at net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType.accept(TypeDescription.java:3364)
    at net.bytebuddy.implementation.attribute.FieldAttributeAppender$ForInstrumentedField.apply(FieldAttributeAppender.java:122)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record$ForExplicitField.apply(TypeWriter.java:270)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:4156)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:174)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2559)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2661)
    at my.package.playground.ByteBuddyHello.main(ByteBuddyHello.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

推荐答案

这是Byte Buddy中的错误;类型注释的解析器需要知道任何类型描述​​的深度,因此可以解析任何类型描述​​的类型路径.对于潜在类型,此深度始终为0,但默认实现采用更复杂的解决方案.

This is a bug in Byte Buddy; the resolver for type annotations needs to know the depth of any type description and therefore resolves the type path of any type description. For latent types, this depth is always 0 but the default implementation applies a more complex solution.

此问题将在下一版本中修复.同时,将潜在类型描述子类化,并重写该方法以返回0.

我决定不更改 TypeDescription.Latent 类型,而是使 InstrumentedType.Default 实现更易于访问.使用后一种类型,该类型允许您定义任何用户都可以看到的循环类型的特征.这样,例如,如果您要定义实施以对此功能进行验证,则可以指定现有的字段和方法.

I decided not to change the TypeDescription.Latent type but rather make the InstrumentedType.Default implementation more accessible. Use the latter type which allows you to define features of the cyclic type which will be visible to any user. This way, you can for example specify existing fields and methods if you want to define Implementations that validate against this feature.

这篇关于字节预算:生成具有循环类型的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆