cglib。不在新版本 JDK 维护,尤其是 JDK 17+
在开发过程中,.java
文件需要经过编译变成 .class
字节码,在到启动、运行,Java 提供了多种方式增强程序的方法:
注解处理器(Annotation Processor)在 JSR 269 中引入,是 javac
的一个工具,只在编译时生效。Annotation Processor 在编译时扫描、编译、处理注解(Annotation)。用户可以自定义注解和注解处理器在编译期间处理一些工作:
META-INF/services
文件Annotation Processor 的应用场景:
Annotation Processor 只提供了在编译时扫描、编译、处理注解(Annotation)功能。如果用户想要在新增 Java 类或修改字节码,都需要使用其他 API 配合:
JavaAgent 在 JDK 1.5 引入,是一种可以动态修改 Java 字节码的技术。JavaAgent 不能独立运行,启动时需要在目标程序的启动参数中添加 -javaagent
参数引入。
JavaAgent 通过 Instrumentation API 与 JVM 交互,Instrumentation API 主要有以下功能:
premain
方法传入代理程序,premain
方法会在 main
方法之前被调用。premain
方法在启动时,在类加载前定义类的 TransFormer,在类加载时更新对应的类的字节码。agentmain
方法实现字节码修改。JVM 提供 Attach API,可以将代理程序 attach(pid)
到另一个运行中的 Java 进程,通过 loadAgent(AgentJarPath)
方法将 JavaAgent jar 包注入到对应的 Java 进程,Java 进程即会调用 agentmain
方法,实现动态字节码修改。如果有 arthas 使用体验,这个过程会很有既视感。agentmain
方法用于在运行时进行字节码改写,分为注册类的 TransFormer 调用和 retransformClasses 函数进行类的重加载premain
方法仅在程序启动时运行,即 main
方法执行前。此时还有很多类没有被加载,这些类无法通过 premain
方法修改字节码。
JavaAgent 的应用场景:
普通反射
ReflectorFactory
MetaClass
MetaObject
ReflectionUtils
ClassUtils
TypeUtils
ClassUtils
FieldUtils
MethodUtils
TypeUtils
ReflectUtil
TypeFactory
, JavaType
, SerializationConfig
, DeserializationConfig
, ClassIntrospector
lambda
其他