gpt4 book ai didi

java - cglib 有替代品吗?

转载 作者:行者123 更新时间:2023-12-04 21:46:22 28 4
gpt4 key购买 nike

关闭。这个问题不符合 Stack Overflow guidelines 。它目前不接受答案。












想改善这个问题吗?更新问题,以便堆栈溢出为 on-topic

7年前关闭。



Improve this question




出于好奇,除了 cglib 之外,是否有任何(稳定的)开源项目用于运行时 Java 代码生成?我为什么要使用它们?

最佳答案

ASM

CGLIB 和几乎所有其他库都建立在 ASM 之上,ASM 本身在非常低的级别上起作用。这对大多数人来说是个障碍,因为您必须了解字节码和一点点 JVMS 才能正确使用它。但是掌握 ASM 无疑是非常有趣的。但是请注意,虽然有一个 great ASM 4 guide ,但在 API 的某些部分,javadoc 文档可能非常简洁,如果它存在的话,但它正在改进。它紧跟 JVM 版本以支持新功能。

但是,如果您需要完全控制,ASM 是您的首选武器。

该项目定期更新;在此编辑时,5.0.4 版已于 2015 年 5 月 15 日发布。

Byte Buddy

Byte Buddy 是一个相当新的库,但提供了 CGLIB 或 Javassist 提供的任何功能等等。 Byte Buddy 可以完全定制到字节码级别,并带有一个富有表现力的领域特定语言,允许非常可读的代码。

  • 支持所有 JVM 字节码版本,包括 Java 8 关于默认方法的一些操作码的语义变化。
  • ByteBuddy 似乎没有受到其他库的缺点
  • 高度可配置
  • 相当快 ( benchmark code )
  • 类型安全流畅 API
  • 类型安全回调

    Javassist advices or custom instrumentation code is based on code in a plain String thus type check and debugging is impossible within this code, while ByteBuddy allows to write those with pure Java hence enforces type checks and allows debugging.

  • 注释驱动(灵活)

    The user callbacks can be configured with annotations allowing to receive the wanted parameters in the callback.

  • 可作为代理使用

    The nifty agent builder allows ByteBuddy to be used as a pure agent or as attaching agent. It allows different kind

  • 非常有据可查
  • 很多例子
  • 干净的代码,~94% 的测试覆盖率
  • 安卓 DEX 支持

  • 主要的缺点可能是,API 对于初学者来说有点冗长,但它被设计为一个可选的 API,形状为代理生成 DSL;没有神奇或可疑的默认值。在操作字节码时,它可能是最安全、最合理的选择。还有多个示例和一个大教程,这不是一个真正的问题。

    2015 年 10 月,该项目收到了 Oracle Duke's choice award 。这时候刚好达到了 1.0.0 milestone ,已经是相当不错的成绩了。

    请注意, 在 2.1.0 版本中已经替换了 CGLIB by Byte Buddy

    Javassist

    Javassist 的 javadoc 比 CGLIB 的要好得多。类工程 API 还可以,但 Javassist 也不完美。特别是,相当于 CGLIB 的 ProxyFactoryEnhancer 也有一些缺点,仅列出一些:
  • 不完全支持桥接方法(即为协变返回类型生成的方法)
  • ClassloaderProvider 是一个静态字段,然后它适用于同一个类加载器中的所有实例
  • 可以欢迎自定义命名(检查签名的 jar)
  • 没有扩展点,几乎所有感兴趣的方法都是私有(private)的,如果我们想改变一些行为,这很麻烦
  • 虽然 Javassist 支持类中的注释属性,但它们在 ProxyFactory 中不受支持。

  • 在面向方面的方面,可以在代理中注入(inject)代码,但是 Javassist 中的这种方法是有限的并且有点容易出错:
  • 方面代码是用纯 Java 字符串编写的,该字符串在操作码
  • 中编译
  • 无类型检查
  • 没有泛型
  • 无 lambda
  • 没有自动(取消)装箱

  • Javassist 也被认为比 Cglib 慢。这主要是由于它读取类文件的方法而不是读取加载的类,例如 CGLIB。公平地说, implementation 本身很难阅读;如果需要在 Javassist 代码中进行更改,则有很多机会破坏某些东西。

    Javassist 也受到不 Activity 的影响,他们迁移到 github circa 2013 似乎已被证明是有用的,因为它显示了来自社区的定期提交和拉取请求。

    这些限制仍然存在于 3.17.1 版本中。版本已升级到 3.20.0 版,但 Javassist 似乎仍然存在对 Java 8 支持的问题。

    JiteScript

    JiteScript 确实看起来像是为 ASM 精心打造的 DSL,它基于最新的 ASM 版本 (4.0)。代码看起来很干净。

    但是 该项目还处于早期阶段,因此 API/行为可以改变,而且文档很糟糕。如果没有放弃,更新很少。

    Proxetta

    这是一个相当新的工具,但它提供了迄今为止最好的人类 API。它允许使用不同类型的代理,例如子类代理(cglib 方法)或编织或委托(delegate)。

    虽然,这个相当罕见,但如果它运作良好,则不存在任何信息。处理字节码时有很多极端情况需要处理。

    AspectJ

    AspectJ 是一个非常强大的工具,用于 面向方面的编程 (仅限)。 AspectJ 操纵字节码来实现它的目标,这样您就可以使用它来实现您的目标。但是,这需要在编译时进行操作;自版本 2.5, 4.1.x 起,spring 在加载时通​​过代理提供编织。

    CGLIB

    自从提出这个问题以来,关于 CGLIB 的一句话已经更新。

    CGLIB 速度非常快,这是它仍然存在的主要原因之一,此外,CGLIB 的效果几乎比迄今为止(2014-2015 年)的任何替代方案都要好。

    一般来说,允许在运行时重写类的库必须避免在重写相应类之前加载任何类型。因此,它们不能使用 Java 反射 API,该 API 要求加载反射中使用的任何类型。相反,他们必须通过 IO(这是一个性能破坏者)读取类文件。这使得 Javassist 或 Proxetta 比 Cglib 慢得多,后者只是通过反射 API 读取方法并覆盖它们。

    但是,CGLIB 不再处于积极开发状态。有最近的版本,但许多人认为这些变化微不足道,大多数人从未更新到版本 3,因为 CGLIB 在上一个版本中引入了一些 severe bugs,这并没有真正建立信心。 3.1 版修复了 3.0 版的很多问题(因为 4.0.3 版 Spring 框架重新打包了 version 3.1 )。

    此外,CGLIB 源代码相当 poor quality,因此我们看不到新的开发人员加入 CGLIB 项目。对于 CGLIB 活跃度的印象,请参阅他们的 mailing list

    请注意,在 proposition on the guice mailing list 之后,CGLIB 现在可用于 github 以使社区能够更好地帮助该项目,它似乎正在工作(多次提交和拉取请求、ci、更新的 maven),但大多数问题仍然存在。

    目前正在开发 3.2.0 版本,并且他们专注于 Java 8,但到目前为止,想要 Java 8 支持的用户必须在构建时使用技巧。但进展非常缓慢。

    众所周知,CGLIB 仍然受到 PermGen 内存泄漏的困扰。但其他项目可能没有经过这么多年的实战考验。

    Compile time annotation Processing

    这当然不是运行时,而是生态系统的重要组成部分,大多数代码生成使用不需要运行时创建。

    这从 Java 5 开始,它带有单独的命令行工具来处理注释: apt ,从 Java 6 开始,注释处理被集成到 Java 编译器中。

    有时您需要明确地传递处理器,现在使用 ServiceLoader 方法(只需将此文件 META-INF/services/javax.annotation.processing.Processor 添加到 jar 中),编译器可以自动检测注释处理器。

    这种代码生成方法也有缺点,它需要大量的工作和对 Java 语言的理解,而不是字节码。这个 API 有点麻烦,而且作为编译器中的插件,必须非常小心,使这段代码成为最具弹性和用户友好的错误消息。

    这里最大的优点是它避免了运行时的另一个依赖,你可以避免永久内存泄漏。并且可以完全控制生成的代码。

    结论

    2002 中,CGLIB 定义了一个新的标准来轻松操作字节码。我们现在拥有的许多工具和方法(CI、覆盖率、TDD 等)当时都不可用或不成熟。 CGLIB 成功地保持了十多年的相关性;这是一个相当不错的成就。与直接操作操作码相比,它速度快且 API 易于使用。

    它定义了关于代码生成的新标准,但现在它不再是因为环境和要求已经改变,所以标准和目标也改变了。

    JVM 发生了变化,并将在最近和 future 的 Java (7/8/9/10) 版本(invokedynamic、默认方法、值类型等)中发生变化。 ASM 定期升级他的 API 和内部组件以遵循这些更改,但 CGLIB 和其他人尚未使用它们。

    虽然注释处理越来越受欢迎,但它不如运行时生成灵活。

    截至 2015 年, Byte Buddy ——虽然在现场相当新——为运行时生成提供了最引人注目的卖点。不错的更新率,作者对 Java 字节码内部结构有深入了解。

    关于java - cglib 有替代品吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2261947/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com