Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。
想改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。
6年前关闭。
Improve this question
出于好奇,除了cglib之外,是否有任何(稳定)开源项目用于运行时Java代码生成?我为什么要使用它们? 它支持所有JVM字节码版本,包括有关默认方法的某些操作码的Java 8语义更改。 ByteBuddy似乎没有遭受其他库具有 的缺点的困扰高度可配置的 相当快(benchmark code) 类型安全流畅的API 输入安全回调
注释驱动(灵活)
可作为代理
记录良好的 许多示例 干净代码,〜94%的测试覆盖率 Android DEX支持
该API的主要缺点可能是,它对于初学者来说有点冗长,但它被设计为采用代理代DSL形式的可选API;没有魔术或可疑的默认值。在处理字节码时,它可能是最安全,最合理的选择。同样,有多个示例和大量教程也不是真正的问题。
在2015年10月,该项目收到了Oracle Duke's choice award。此时,它刚刚达到1.0.0 milestone,这是一个很大的成就。
请注意,mockito在版本2.1.0中替换了CGLIB by Byte Buddy。
Javassist javassist
Javassist的Javadoc比CGLIB更好。类工程API可以,但是Javassist也不是完美的。特别是,相当于CGLIB的
不完全支持Bridge方法(即为协变返回类型生成的方法) 自定义命名可能会受到欢迎(带有签名 jar 的检查) 没有扩展点,几乎所有感兴趣的方法都是私有(private)的,如果我们想更改某些行为,这将很麻烦 虽然Javassist支持类中的注释属性,但
在面向方面方面,可以将代码注入(inject)代理中,但是Javassist中的这种方法是有限的,并且容易出错:
方面代码以纯Java字符串编写,并以操作码 进行编译无类型检查 没有泛型 no 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 jodd
这是一个相当新的工具,但是它提供了迄今为止最好的人工API。它允许使用不同类型的代理,例如子类代理(cglib方法)或编织或委派。
尽管这是相当少见的,但如果运作良好,则没有任何信息。处理字节码时有很多特殊情况需要处理。
AspectJ aspectj
AspectJ是用于面向方面的编程(仅)的非常强大的工具。 AspectJ通过操纵字节码来实现其目标,从而使您可以使用它来实现目标。但是,这需要在编译时进行操作。从2.5和4.1.x版本开始,通过代理在加载时编织Spring产品。
CGLIB cglib
自问这个问题以来,有关CGLIB的词汇已更新。
CGLIB的运行速度非常快,这是它仍然存在的主要原因之一,而且CGLIB的运行情况几乎比现在(2014-2015年)的任何替代产品都要好。
一般来说,允许在运行时重写类的库必须避免在重写相应类之前加载任何类型。因此,它们不能使用Java反射API,而Java反射API要求加载反射中使用的任何类型。相反,他们必须通过IO(这是性能破坏者)读取类文件。例如,这使得Javassist或Proxetta比Cglib慢得多,后者仅通过反射API读取方法并覆盖它们。
但是,CGLIB不再处于积极开发中。有最新版本,但许多人认为这些更改微不足道,因为CGLIB在上一版本中引入了severe bugs,但大多数人从未更新到版本3,但实际上并没有建立起信心。 3.1版解决了3.0版的许多问题(因为4.0.3版Spring框架重新打包了version 3.1)。
另外,CGLIB源代码的格式是poor quality,因此我们看不到新的开发人员加入CGLIB项目。对于CGLIB的活跃性印象,请参阅其mailing list。
请注意,在proposition on the guice mailing list之后,现在可以在github上使用CGLIB,以使社区能够更好地帮助该项目,它似乎正在工作(多次提交和请求,ci,更新的maven),但仍然存在大多数问题。
目前,正在开发3.2.0版,并且他们将精力集中在Java 8上,但是到目前为止,想要Java 8支持的用户必须在构建时使用技巧。但是进展非常缓慢。
CGLIB仍然因PermGen内存泄漏而困扰。但是其他项目可能没有经过这么多年的战斗测试。
Compile time annotation Processing annotation-processing
当然,这不是运行时,而是生态系统的重要组成部分,大多数代码生成用法不需要创建运行时。
这从Java 5开始,Java 5带有单独的命令行工具来处理注释:
有时需要您显式传递处理器,现在使用
这种代码生成方法也有缺点,它也需要大量工作并且需要Java语言(而不是字节码)的理解。该API有点麻烦,并且因为它是编译器中的插件,因此必须格外小心,以使该代码成为最有弹性和用户友好的错误消息。
这里最大的好处是,它避免了运行时的另一个依赖关系,可以避免permgen内存泄漏。并且可以完全控制生成的代码。
结论
CGLIB在2002中定义了一个新的标准,可以轻松地操作字节码。当今我们拥有的许多工具和方法论(CI,覆盖率,TDD等)当时都不可用或不成熟。十多年来,CGLIB一直与时俱进;这是一个相当不错的成就。与直接操作操作码相比,它的运行速度快且具有易于使用的API。
它定义了有关代码生成的新标准,但如今由于环境和要求已发生变化,因此不再存在,标准和目标也已发生变化。
JVM已更改,并将在最近和将来的Java(7/8/9/10)版本(调用动态,默认方法,值类型等)中更改。 ASM会定期更新其API和内部组件以适应这些更改,但是CGLIB和其他人员尚未使用它们。
尽管注释处理越来越受青睐,但它不像运行时生成那样灵活。
截至2015年, Byte Buddy 虽然是新手,但为运行时生成提供了最引人注目的卖点。相当不错的更新速度,并且作者对Java字节码内部知识非常了解。
想改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。
6年前关闭。
Improve this question
出于好奇,除了cglib之外,是否有任何(稳定)开源项目用于运行时Java代码生成?我为什么要使用它们?
最佳答案
ASM java-asm
CGLIB和几乎所有其他库都建立在ASM之上,而ASM本身的作用很低。对于大多数人来说,这是一个阻止对象,因为您必须了解字节码和JVMS的一点点才能正确使用它。但是掌握ASM无疑是非常有趣的。但是请注意,尽管存在和 ASM 4 guide,但在API的某些部分中,如果javadoc文档完全存在,它可能会非常简洁,但是正在对其进行改进。它紧密遵循JVM版本以支持新功能。
但是,如果您需要完全控制,ASM是您的首选武器。
该项目定期更新;在2015年5月15日发布此编辑版本5.0.4时。
Byte Buddy byte-buddy
Byte Buddy是一个相当新的库,但提供了CGLIB或Javassist提供的任何功能以及更多功能。 Byte Buddy可以完全自定义到字节码级别,并带有一种表达性强的特定于域的语言,该语言允许非常可读的代码。
该API的主要缺点可能是,它对于初学者来说有点冗长,但它被设计为采用代理代DSL形式的可选API;没有魔术或可疑的默认值。在处理字节码时,它可能是最安全,最合理的选择。同样,有多个示例和大量教程也不是真正的问题。
在2015年10月,该项目收到了Oracle Duke's choice award。此时,它刚刚达到1.0.0 milestone,这是一个很大的成就。
请注意,mockito在版本2.1.0中替换了CGLIB by Byte Buddy。
Javassist javassist
Javassist的Javadoc比CGLIB更好。类工程API可以,但是Javassist也不是完美的。特别是,相当于CGLIB的
ProxyFactory
的Enhancer
也有一些缺点,仅举几例:ClassloaderProvider
而是一个静态字段,然后它应用于同一类加载器中的所有实例ProxyFactory
不支持它们。 在面向方面方面,可以将代码注入(inject)代理中,但是Javassist中的这种方法是有限的,并且容易出错:
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 jodd
这是一个相当新的工具,但是它提供了迄今为止最好的人工API。它允许使用不同类型的代理,例如子类代理(cglib方法)或编织或委派。
尽管这是相当少见的,但如果运作良好,则没有任何信息。处理字节码时有很多特殊情况需要处理。
AspectJ aspectj
AspectJ是用于面向方面的编程(仅)的非常强大的工具。 AspectJ通过操纵字节码来实现其目标,从而使您可以使用它来实现目标。但是,这需要在编译时进行操作。从2.5和4.1.x版本开始,通过代理在加载时编织Spring产品。
CGLIB cglib
自问这个问题以来,有关CGLIB的词汇已更新。
CGLIB的运行速度非常快,这是它仍然存在的主要原因之一,而且CGLIB的运行情况几乎比现在(2014-2015年)的任何替代产品都要好。
一般来说,允许在运行时重写类的库必须避免在重写相应类之前加载任何类型。因此,它们不能使用Java反射API,而Java反射API要求加载反射中使用的任何类型。相反,他们必须通过IO(这是性能破坏者)读取类文件。例如,这使得Javassist或Proxetta比Cglib慢得多,后者仅通过反射API读取方法并覆盖它们。
但是,CGLIB不再处于积极开发中。有最新版本,但许多人认为这些更改微不足道,因为CGLIB在上一版本中引入了severe bugs,但大多数人从未更新到版本3,但实际上并没有建立起信心。 3.1版解决了3.0版的许多问题(因为4.0.3版Spring框架重新打包了version 3.1)。
另外,CGLIB源代码的格式是poor quality,因此我们看不到新的开发人员加入CGLIB项目。对于CGLIB的活跃性印象,请参阅其mailing list。
请注意,在proposition on the guice mailing list之后,现在可以在github上使用CGLIB,以使社区能够更好地帮助该项目,它似乎正在工作(多次提交和请求,ci,更新的maven),但仍然存在大多数问题。
目前,正在开发3.2.0版,并且他们将精力集中在Java 8上,但是到目前为止,想要Java 8支持的用户必须在构建时使用技巧。但是进展非常缓慢。
CGLIB仍然因PermGen内存泄漏而困扰。但是其他项目可能没有经过这么多年的战斗测试。
Compile time annotation Processing annotation-processing
当然,这不是运行时,而是生态系统的重要组成部分,大多数代码生成用法不需要创建运行时。
这从Java 5开始,Java 5带有单独的命令行工具来处理注释:
apt
,从Java 6开始,注释处理已集成到Java编译器中。有时需要您显式传递处理器,现在使用
ServiceLoader
方法(只需将此META-INF/services/javax.annotation.processing.Processor
文件添加到jar中),编译器就可以自动检测注释处理器。这种代码生成方法也有缺点,它也需要大量工作并且需要Java语言(而不是字节码)的理解。该API有点麻烦,并且因为它是编译器中的插件,因此必须格外小心,以使该代码成为最有弹性和用户友好的错误消息。
这里最大的好处是,它避免了运行时的另一个依赖关系,可以避免permgen内存泄漏。并且可以完全控制生成的代码。
结论
CGLIB在2002中定义了一个新的标准,可以轻松地操作字节码。当今我们拥有的许多工具和方法论(CI,覆盖率,TDD等)当时都不可用或不成熟。十多年来,CGLIB一直与时俱进;这是一个相当不错的成就。与直接操作操作码相比,它的运行速度快且具有易于使用的API。
它定义了有关代码生成的新标准,但如今由于环境和要求已发生变化,因此不再存在,标准和目标也已发生变化。
JVM已更改,并将在最近和将来的Java(7/8/9/10)版本(调用动态,默认方法,值类型等)中更改。 ASM会定期更新其API和内部组件以适应这些更改,但是CGLIB和其他人员尚未使用它们。
尽管注释处理越来越受青睐,但它不像运行时生成那样灵活。
截至2015年, Byte Buddy 虽然是新手,但为运行时生成提供了最引人注目的卖点。相当不错的更新速度,并且作者对Java字节码内部知识非常了解。
关于java - 有cglib的替代品吗? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2261947/
10-08 20:35