本文目录导读:

我来为你详细介绍Java字节码增强的实现案例,字节码增强是在Java类加载时或运行时修改字节码的技术,常见应用包括AOP、性能监控、热部署等。
基础环境准备
<!-- pom.xml 依赖 -->
<dependencies>
<!-- Javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.2-GA</version>
</dependency>
<!-- ASM -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.6</version>
</dependency>
<!-- Byte Buddy -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.9</version>
</dependency>
</dependencies>
演示用的目标类
// 目标类:用户服务
public class UserService {
public String getUserInfo(String userId) {
// 模拟业务逻辑
delay(100);
return "User-" + userId;
}
public void updateUser(String userId, String name) {
// 模拟业务逻辑
delay(200);
System.out.println("Update user: " + userId + ", name: " + name);
}
private void delay(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Javassist实现字节码增强
import javassist.*;
import java.lang.reflect.Method;
/**
* Javassist字节码增强示例
* 功能:方法耗时统计、参数日志记录
*/
public class JavassistEnhancer {
// 静态代理方式
public static Class<?> enhanceUserService() throws Exception {
ClassPool pool = ClassPool.getDefault();
// 获取目标类
CtClass ctClass = pool.get("UserService");
// 添加一个方法耗时统计的注解(可选)
ctClass.addAnnotation(new javassist.bytecode.annotation.Annotation(
"java.lang.Deprecated", ctClass.getClassFile().getConstPool()
));
// 增强方法:添加耗时统计
CtMethod[] methods = ctClass.getDeclaredMethods();
for (CtMethod method : methods) {
if (method.isEmpty()) {
continue;
}
// 为方法添加耗时统计
String methodName = method.getName();
String enhancedBody = buildEnhancedBody(method, methodName);
// 替换方法体
method.setBody(enhancedBody);
System.out.println("增强方法: " + methodName);
}
// 返回增强后的类
return ctClass.toClass();
}
/**
* 构建增强的方法体
*/
private static String buildEnhancedBody(CtMethod method, String methodName) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("{");
sb.append(" long startTime = System.currentTimeMillis();");
sb.append(" System.out.println(\"[Javassist] 调用方法: " + methodName + "\");");
sb.append(" try {");
// 如果是void方法
if (method.getReturnType().equals(CtPrimitiveType.voidType)) {
sb.append(" " + methodName + "$impl($$);");
} else {
sb.append(" Object result = " + methodName + "$impl($$);");
sb.append(" return ($r) result;");
}
sb.append(" } finally {");
sb.append(" long endTime = System.currentTimeMillis();");
sb.append(" System.out.println(\"[Javassist] 方法: " + methodName + "耗时: \" + (endTime - startTime) + \"ms\");");
sb.append(" }");
sb.append("}");
return sb.toString();
}
/**
* 运行时增强(自定义ClassLoader方式)
*/
public static Object createEnhancedInstance() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("UserService");
// 复制原有方法
CtMethod method = ctClass.getDeclaredMethod("getUserInfo");
// 创建增强方法
String newMethodName = "getUserInfoEnhanced";
CtMethod enhancedMethod = CtNewMethod.copy(method, newMethodName, ctClass, null);
// 修改原方法
method.setBody("{"
+ "long start = System.currentTimeMillis();"
+ "Object result = " + newMethodName + "($$);"
+ "long end = System.currentTimeMillis();"
+ "System.out.println(\"getUserInfo 耗时: \" + (end - start) + \"ms\");"
+ "return ($r) result;"
+ "}");
// 添加增强方法
ctClass.addMethod(enhancedMethod);
// 创建实例
Class<?> enhancedClass = ctClass.toClass();
return enhancedClass.getDeclaredConstructor().newInstance();
}
}
ASM实现字节码增强
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;
import java.lang.reflect.Method;
/**
* ASM字节码增强示例
*/
public class ASMEnhancer {
/**
* 自定义ClassVisitor
*/
public static class EnhanceClassVisitor extends ClassVisitor {
public EnhanceClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM9, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
// 只增强非抽象方法
if (mv != null && !name.equals("<init>") && !name.equals("<clinit>")) {
return new EnhanceMethodVisitor(mv, access, name, descriptor);
}
return mv;
}
}
/**
* 自定义MethodVisitor
*/
public static class EnhanceMethodVisitor extends AdviceAdapter {
private final String methodName;
protected EnhanceMethodVisitor(MethodVisitor mv, int access, String name, String descriptor) {
super(Opcodes.ASM9, mv, access, name, descriptor);
this.methodName = name;
}
@Override
protected void onMethodEnter() {
// 方法进入时打印日志
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("[ASM] 进入方法: " + methodName);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
// 开始计时
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
mv.visitVarInsn(Opcodes.LSTORE, 10);
}
@Override
protected void onMethodExit(int opcode) {
if (opcode != Opcodes.ATHROW) {
// 计算耗时
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
mv.visitVarInsn(Opcodes.LLOAD, 10);
mv.visitInsn(Opcodes.LSUB);
mv.visitVarInsn(Opcodes.LSTORE, 12);
// 打印耗时
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false);
mv.visitLdcInsn("[ASM] 方法 " + methodName + " 耗时: ");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
mv.visitVarInsn(Opcodes.LLOAD, 12);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;", false);
mv.visitLdcInsn("ms");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
}
}
}
/**
* 使用ASM增强类
*/
public static byte[] enhanceClass(byte[] originalClass) {
ClassReader classReader = new ClassReader(originalClass);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
EnhanceClassVisitor visitor = new EnhanceClassVisitor(classWriter);
classReader.accept(visitor, 0);
return classWriter.toByteArray();
}
}
Byte Buddy实现字节码增强
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.*;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
/**
* Byte Buddy字节码增强示例(推荐使用)
*/
public class ByteBuddyEnhancer {
/**
* 方式一:使用Advice进行方法增强
*/
public static Class<?> enhanceWithAdvice() throws Exception {
DynamicType.Unloaded<UserService> unloaded = new ByteBuddy()
.subclass(UserService.class)
.method(ElementMatchers.named("getUserInfo"))
.intercept(Advice.to(PerformanceAdvice.class))
.method(ElementMatchers.named("updateUser"))
.intercept(Advice.to(LoggingAdvice.class));
return unloaded.load(UserService.class.getClassLoader())
.getLoaded();
}
/**
* Advice类:性能监控
*/
public static class PerformanceAdvice {
@Advice.OnMethodEnter
public static long enter(@Advice.Origin Method method) {
System.out.println("[Byte Buddy] 进入方法: " + method.getName());
return System.nanoTime();
}
@Advice.OnMethodExit
public static void exit(@Advice.Enter long startTime,
@Advice.Origin Method method,
@Advice.Return Object result) {
long duration = (System.nanoTime() - startTime) / 1_000_000;
System.out.println("[Byte Buddy] 方法 " + method.getName() +
" 耗时: " + duration + "ms,返回值: " + result);
}
}
/**
* Advice类:日志记录
*/
public static class LoggingAdvice {
@Advice.OnMethodEnter
public static void enter(@Advice.AllArguments Object[] args,
@Advice.Origin Method method) {
System.out.println("[Byte Buddy] 调用: " + method.getName() +
",参数: " + java.util.Arrays.toString(args));
}
@Advice.OnMethodExit
public static void exit(@Advice.Origin Method method) {
System.out.println("[Byte Buddy] 方法执行完成: " + method.getName());
}
}
/**
* 方式二:使用MethodDelegation
*/
public static Class<?> enhanceWithDelegation() throws Exception {
DynamicType.Unloaded<UserService> unloaded = new ByteBuddy()
.subclass(UserService.class)
.method(ElementMatchers.any())
.intercept(MethodDelegation.to(Interceptor.class));
return unloaded.load(UserService.class.getClassLoader())
.getLoaded();
}
/**
* 拦截器类
*/
public static class Interceptor {
@RuntimeType
public static Object intercept(@This Object target,
@Origin Method method,
@AllArguments Object[] args,
@SuperCall Callable<?> callable) throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("[Byte Buddy] 调用方法: " + method.getName());
try {
Object result = callable.call();
System.out.println("[Byte Buddy] 方法返回: " + result);
return result;
} finally {
long duration = System.currentTimeMillis() - startTime;
System.out.println("[Byte Buddy] 方法耗时: " + duration + "ms");
}
}
}
}
完整测试示例
import java.lang.reflect.Method;
/**
* 测试类
*/
public class BytecodeEnhancementTest {
public static void main(String[] args) throws Exception {
System.out.println("========== 1. Javassist增强测试 ==========");
testJavassist();
System.out.println("\n========== 2. ASM增强测试 ==========");
testASM();
System.out.println("\n========== 3. Byte Buddy增强测试 ==========");
testByteBuddy();
}
/**
* 测试Javassist
*/
private static void testJavassist() throws Exception {
Class<?> enhancedClass = JavassistEnhancer.enhanceUserService();
Object instance = enhancedClass.getDeclaredConstructor().newInstance();
Method method = enhancedClass.getMethod("getUserInfo", String.class);
Object result = method.invoke(instance, "1001");
System.out.println("Javassist增强结果: " + result);
}
/**
* 测试ASM
*/
private static void testASM() throws Exception {
// 读取原始类字节码
ClassLoader classLoader = UserService.class.getClassLoader();
java.io.InputStream is = classLoader.getResourceAsStream(
"UserService.class".replace('.', '/')
);
byte[] originalBytes = is.readAllBytes();
// 增强字节码
byte[] enhancedBytes = ASMEnhancer.enhanceClass(originalBytes);
// 自定义类加载器加载增强后的类
ClassLoader enhancedClassLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals("UserService")) {
return defineClass(name, enhancedBytes, 0, enhancedBytes.length);
}
return super.loadClass(name);
}
};
Class<?> enhancedClass = enhancedClassLoader.loadClass("UserService");
Object instance = enhancedClass.getDeclaredConstructor().newInstance();
Method method = enhancedClass.getMethod("getUserInfo", String.class);
Object result = method.invoke(instance, "1002");
System.out.println("ASM增强结果: " + result);
}
/**
* 测试Byte Buddy
*/
private static void testByteBuddy() throws Exception {
Class<?> enhancedClass = ByteBuddyEnhancer.enhanceWithAdvice();
Object instance = enhancedClass.getDeclaredConstructor().newInstance();
Method method = enhancedClass.getMethod("getUserInfo", String.class);
Object result = method.invoke(instance, "1003");
System.out.println("Byte Buddy增强结果: " + result);
// 测试另一个方法
Method updateMethod = enhancedClass.getMethod("updateUser", String.class, String.class);
updateMethod.invoke(instance, "1003", "张三");
}
}
实际应用案例:AOP日志框架
import java.lang.annotation.*;
import java.lang.reflect.Method;
/**
* 自定义注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
String value() default "";
}
/**
* AOP日志增强器(企业级应用)
*/
public class LoggingEnhancer {
/**
* 使用Byte Buddy实现全面的AOP功能
*/
public static Object enhance(Object target) throws Exception {
DynamicType.Unloaded<Object> unloaded = new ByteBuddy()
.subclass(target.getClass())
.method(ElementMatchers.isAnnotatedWith(Loggable.class))
.intercept(MethodDelegation.to(AspectLoggerInterceptor.class))
.make();
Class<?> enhancedClass = unloaded.load(target.getClass().getClassLoader())
.getLoaded();
return enhancedClass.getDeclaredConstructor().newInstance();
}
/**
* 切面拦截器
*/
public static class AspectLoggerInterceptor {
@RuntimeType
public static Object intercept(@This Object target,
@Origin Method method,
@AllArguments Object[] args,
@SuperCall Callable<?> callable) throws Exception {
// 前置通知
LogContext context = new LogContext();
context.setMethod(method);
context.setArgs(args);
context.setStartTime(System.currentTimeMillis());
try {
// 执行目标方法
Object result = callable.call();
// 后置通知
logSuccess(context, result);
return result;
} catch (Exception e) {
// 异常通知
logError(context, e);
throw e;
} finally {
// 最终通知
logFinally(context);
}
}
private static void logSuccess(LogContext ctx, Object result) {
System.out.println(String.format(
"[AOP] 方法 %s 成功执行,参数: %s,结果: %s",
ctx.getMethod().getName(),
Arrays.toString(ctx.getArgs()),
result
));
}
private static void logError(LogContext ctx, Exception e) {
System.err.println(String.format(
"[AOP] 方法 %s 执行异常: %s",
ctx.getMethod().getName(),
e.getMessage()
));
}
private static void logFinally(LogContext ctx) {
long duration = System.currentTimeMillis() - ctx.getStartTime();
System.out.println(String.format(
"[AOP] 方法 %s 执行耗时: %dms",
ctx.getMethod().getName(),
duration
));
}
}
/**
* 日志上下文
*/
public static class LogContext {
private Method method;
private Object[] args;
private long startTime;
// getter/setter...
}
}
使用注意事项
/**
* 性能优化建议
*/
public class EnhancementBestPractices {
/**
* 1. 缓存增强类
*/
public class ClassCache {
private final Map<String, Class<?>> cache = new ConcurrentHashMap<>();
public Class<?> getEnhancedClass(String className) {
return cache.computeIfAbsent(className, this::createClass);
}
private Class<?> createClass(String className) {
// 增强逻辑
return UserService.class;
}
}
/**
* 2. 用于生产环境的Agent方式
*/
public static class ByteBuddyAgentExample {
public static void premain(String args, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith("com.example"))
.transform((builder, typeDescription, classLoader, module) ->
builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(Interceptor.class))
)
.installOn(inst);
}
}
}
字节码增强的核心价值在于:
- 非侵入式:不需要修改原有业务代码
- 性能监控:方法耗时、参数记录
- 安全控制:权限验证、数据脱敏
- 热部署:动态更新类定义
推荐优先使用 Byte Buddy(API简单、功能强大),ASM(性能最优但复杂度高),Javassist(简单但性能略差)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播