【问题标题】:Generating methods with generic types with Asm bytecode generator (ClassWriter)使用 Asm 字节码生成器 (ClassWriter) 生成具有泛型类型的方法
【发布时间】:2011-03-16 02:36:23
【问题描述】:

使用 Asm 很容易定义简单的 getter 和 setter(幸运的是,它甚至在他们的 FAQ 中都有解释)。但是有一件事没有提到,而且我一直找不到文档,那就是如何使用泛型类型信息来实现这些。

我实际上能够很容易地确定泛型类型信息本身(因为代码将采用现有的字段和/或方法,并且存在完整的泛型类型处理和解析)。我只需要为包含泛型类型的类型生成泛型版本。

我希望这与修改签名 Asm ClassWriter/MethodVisitor 调用一样简单,但文档中的一些 cmets 表明它可能并不那么容易(因为泛型信息存储在与常规信息不同的位置)。

EDIT:看起来入口点是“ClassWriter.visitField/Method(...., String signature) - 注意它是包含普通非泛型类信息的“描述”,但是术语“签名”(在 JLS 中)专门指泛型,包括类型信息。

【问题讨论】:

    标签: java generics code-generation bytecode java-bytecode-asm


    【解决方案1】:

    您可以使用 ASM 的 SignatureWriter 类构建签名。

    例如,假设您希望为此方法编写签名:

    public <K> void doSomething(K thing)
    

    您可以使用以下代码:

    SignatureWriter signature = new SignatureWriter();
    signature.visitFormalTypeParameter("K");
    
    // Ensure that <K> extends java.lang.Object
    {
        SignatureVisitor classBound = signature.visitClassBound();
        classBound.visitClassType(Type.getInternalName(Object.class));
        classBound.visitEnd();
    }
    
    // The parameter uses the <K> type variable
    signature.visitParameterType().visitTypeVariable("K");
    
    // The return type uses the void primitive ('V')
    signature.visitReturnType().visitBaseType('V');
    
    signature.visitEnd();
    
    String signatureString = signature.toString();
    

    相当于:

    String signatureString = "<K:Ljava/lang/Object;>(TK;)V;"
    

    【讨论】:

    • 这很有用,谢谢。我现在的具体问题似乎是生成的签名以某种方式未正确写入类文件,尽管我使用了正确的格式(据我所知)。但也许我应该仔细检查 SignatureWriter 以确保...
    • @StaxMan:我也遇到了麻烦。也许这篇文章会有所帮助:Classworking toolkit: Generics with ASM
    • 啊!我终于在我的代码中找到了真正的问题:我在 ClassVisitor.visit(); 中有参数 V1_2;这需要 V1_5 或更高版本才能支持泛型(和注释)。感谢您的帮助!
    • @StaxMan:不客气!哇,您使用 1.2 版有什么特别的原因吗?我从未见过支持老年虚拟机的那种程度的奉献精神。 :)
    • 不,一点也不,它可能只是来自一些遗留代码。它绝对没有被明确选择;包本身(使用 ASM)无论如何都需要 1.5,很快可能需要 1.6。
    【解决方案2】:

    根据我的经验,大多数动态字节码生成库都没有很好地支持泛型类型;但是删除的类工作得很好(当然,除非你想在以后反省这些类)。

    【讨论】:

    • 不幸的是,我确实需要自省——这就是使用库实际构造序列化器和反序列化器的方式。 :-/ 是的,代码擦除可以正常工作...我可能不得不找到另一种方法来使事情正常进行,也许是通过添加新的注释来有效地复制签名。
    猜你喜欢
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多