我知道Javassist是一个Java库,它提供了一种操作应用程序Java字节码的方法。
好的,但为什么我们需要操作字节码?
有什么真实的例子吗? 任何真正的应用程序,javassist使用?
答案 0 :(得分:33)
一个常见的应用程序是在运行时生成代理类,即在运行时创建一个拦截所有方法调用的子类。例子:
Hibernate 使用Proxies拦截实体上的方法调用来实现延迟加载,即在首次访问时从数据库中获取对象。
Spring Framework uses Proxies to implement its AOP support,其中包括支持声明性事务。它还使用代理来强制执行适当的范围。
EJB 使用代理实现容器管理事务,授权检查以及应用用户定义的拦截器。
CDI 实现还必须代理托管bean以确保正确的范围。我怀疑他们也使用字节码工程库。
我最近使用Javassist为方法返回值实现透明缓存,方法是拦截所有方法调用,并且只在第一次调用时委托给超级实现。
请注意java.lang.reflect.Proxy
可以在运行时生成代理类,但只能实现接口,而不能扩展类。所有上述用例都需要代理类。
答案 1 :(得分:15)
字节码操作很有用且必要,尤其是当您没有某些项目的源代码时。假设你只为某个项目提供了字节码(就像一个jar文件),但是你想以某种方式改变代码的行为,字节码操作库可以在这种情况下提供帮助。字节码操作的优点是您不需要重新编译代码,并且可以在操作后直接执行它。
我使用字节码操作来进行一些程序分析。给定一个库,我想知道在运行时调用了库中的哪些方法。我可以使用字节码操作在方法的开头插入System.out.println("method_name");
语句。因此,在运行时,它将打印出已调用的方法。
一些字节码操作库是:
答案 2 :(得分:1)
扩展Meriton的答案并提供一个真实的使用示例:
Hibernate-core(5.2.8.Final)使用javaassit(3.20.0-GA):
https://mvnrepository.com/artifact/org.hibernate/hibernate-core/5.2.8.Final
答案 3 :(得分:0)
ASM项目的用户页面列出了几十个广泛使用的Java项目和框架,使用ASM进行字节码分析和操作。 http://asm.ow2.org/users.html