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 的应用场景:
普通反射
ReflectorFactoryMetaClassMetaObjectReflectionUtilsClassUtilsTypeUtilsClassUtilsFieldUtilsMethodUtilsTypeUtilsReflectUtilTypeFactory, JavaType, SerializationConfig, DeserializationConfig, ClassIntrospectorlambda
其他