轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

    • 核心

      • Java8--Lambda 表达式、Stream 和时间 API
      • Java集合
      • Java IO
      • Java 文件操作
      • Java 网络编程
      • Java运行期动态能力
        • 一、编译期与运行期的区别
          • 1、编译期
          • 2、运行期
        • 二、类加载器
          • 1、类加载器的层次结构
          • 2、自定义类加载器示例
          • 3、类加载器的实际应用场景
          • 4、类加载的生命周期
        • 三、反射
          • 1、反射的核心类
          • 2、获取Class对象的三种方式
          • 3、动态调用方法
          • 4、动态操作字段
          • 5、反射的性能优化
          • 6、vs 反射
        • 四、动态代理
          • 1、JDK动态代理
          • 2、动态代理的应用场景
        • 五、字节码生成
          • 1、字节码操作框架对比
          • 2、ASM框架
          • 3、CGLIB动态代理
          • 4、字节码生成 vs javac编译器
          • 5、22 新特性:ClassFile API(预览)
        • 六、AOP(面向切面编程)
          • 1、AOP的核心概念
          • 2、AOP 示例
          • 3、AOP的实现方式
          • 4、AOP的典型应用场景
        • 七、Agent
          • 1、Agent 的工作原理
          • 2、两种加载方式
          • 3、示例:监控类加载
          • 4、Agent 的实际应用
          • 4.1、APM(应用性能监控)
          • 4.2、开发工具
          • 4.3、字节码增强示例
        • 八、总结
          • 1、技术关系图谱
          • 2、核心要点
          • 3、技术选型建议
          • 4、未来展望
      • Java可插入注解处理器
      • Java基准测试(JMH)
      • Java性能分析(Profiler)
      • Java调试(JDI与JDWP)
      • Java管理与监控(JMX)
      • Java加密体系(JCA)
      • Java服务发现(SPI)
      • Java随机数生成研究
      • Java数据库连接(JDBC)
      • Java历代版本新特性
      • 写好Java Doc
      • 聊聊classpath及其资源获取
    • 并发

    • 经验

    • JVM

    • 企业应用

  • Spring

  • 其他语言

  • 工具

  • 后端
  • Java
  • 核心
轩辕李
2022-01-03
目录

Java运行期动态能力

从宏观上看,Java程序可以分为两大阶段:编译期和运行期。

# 一、编译期与运行期的区别

# 1、编译期

编译期过程大致分为三个阶段:

  • 前端编译:如 javac,将 .java 源文件编译成 .class 字节码文件
  • 后端运行时编译:如 JIT(Just-In-Time),在运行时将热点代码编译成本地机器码
  • 静态提前编译:如 AOT(Ahead-Of-Time)、GraalVM,在部署前将字节码编译成本地机器码

编译期的动态能力相对有限,主要体现在:

  • JIT 编译器的优化参数配置
  • JSR 269 提供的插入式注解处理器(Pluggable Annotation Processing API)
    • 典型应用:Lombok 通过注解处理器在编译期自动生成 getter/setter 等代码
    • 其他应用:MapStruct、Dagger2 等框架也使用此技术

# 2、运行期

运行期是Java展现强大动态能力的阶段,提供了丰富的API和机制来实现运行时的类操作、方法调用和字节码修改。


本文将深入探讨Java运行期的六大动态能力:

  1. 类加载器:动态加载和定义类
  2. 反射:运行时检查和操作类、方法、字段
  3. 动态代理:运行时创建代理对象
  4. 字节码生成:直接操作和生成字节码
  5. AOP:面向切面编程的实现
  6. Java Agent:JVM级别的字节码增强

下面我们逐一深入探讨。

# 二、类加载器

类加载器(ClassLoader)是Java动态性的基础,它负责在运行时查找、加载和定义类。Java的类加载机制采用了双亲委派模型,确保类加载的安全性和唯一性。

# 1、类加载器的层次结构

  1. 启动类加载器(Bootstrap ClassLoader):加载核心Java类库(rt.jar)
  2. 扩展类加载器(Extension ClassLoader):加载扩展目录中的类
  3. 应用类加载器(Application ClassLoader):加载应用程序类路径中的类
  4. 自定义类加载器:开发者可以继承 ClassLoader 实现自定义加载逻辑

# 2、自定义类加载器示例

下面演示如何实现一个从网络动态加载 class 文件的类加载器:

public class NetworkClassLoader extends ClassLoader {

    private String rootUrl;

    public NetworkClassLoader(String rootUrl) {
        super();
        this.rootUrl = rootUrl;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = null;
        byte[] classData = getClassData(name);  //根据类的二进制名称,获得该class文件的字节码数组  
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        clazz = defineClass(name, classData, 0, classData.length);  //将class的字节码数组转换成Class类的实例
        return clazz;
    }

    private byte[] getClassData(String name) {
        InputStream is = null;
        try {
            String path = classNameToPath(name);
            URL url = new URL(path);
            byte[] buff = new byte[1024 * 4];
            int len = -1;
            is = url.openStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((len = is.read(buff)) != -1) {
                baos.write(buff, 0, len);
            }
            return baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private String classNameToPath(String name) {
        return rootUrl + "/" + name.replace(".", "/") + ".class";
    }
}

测试代码:

public static void main(String[] args) {
    try {
        String rootUrl = "http://localhost:8090/";
        NetworkClassLoader networkClassLoader = new NetworkClassLoader(rootUrl);
        String classname = "classLoad.Test";
        Class<?> clazz = networkClassLoader.loadClass(classname);
        System.out.println(clazz.getClassLoader());  // 打印类加载器
        Object newInstance = clazz.getDeclaredConstructor().newInstance();
        clazz.getMethod("getStr").invoke(newInstance);  // 调用方法
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# 3、类加载器的实际应用场景

  1. 热部署:在不重启应用的情况下更新类定义
  2. 模块化系统:如 OSGi 框架,每个模块有独立的类加载器
  3. Web容器:Tomcat 为每个 Web 应用创建独立的类加载器,实现应用隔离
  4. 插件系统:动态加载和卸载插件,如 Jenkins、IntelliJ IDEA
  5. 加密保护:加载加密的 class 文件,在加载时解密

# 4、类加载的生命周期

  1. 加载(Loading):通过类的全限定名获取二进制字节流
  2. 验证(Verification):确保字节流符合JVM规范
  3. 准备(Preparation):为静态变量分配内存并设置初始值
  4. 解析(Resolution):将符号引用转换为直接引用
  5. 初始化(Initialization):执行类构造器 <clinit>() 方法

更多细节请参考:类加载器机制详解 (opens new window)

# 三、反射

反射(Reflection)是Java提供的一种强大机制,允许程序在运行时检查和操作类、接口、字段和方法的信息。通过反射,我们可以突破编译期的限制,实现真正的动态编程。

# 1、反射的核心类

  • java.lang.Class:代表类的实体,在运行时表示类和接口
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造方法

# 2、获取Class对象的三种方式

// 方式1:通过类名.class
Class<?> clazz1 = String.class;

// 方式2:通过对象.getClass()
String str = "Hello";
Class<?> clazz2 = str.getClass();

// 方式3:通过Class.forName()
Class<?> clazz3 = Class.forName("java.lang.String");

# 3、动态调用方法

Class<?> klass = MethodClass.class;
// 创建实例(Java 9后推荐使用getDeclaredConstructor())
Object obj = klass.getDeclaredConstructor().newInstance();
// 获取方法
Method method = klass.getMethod("add", int.class, int.class);
// 调用方法
Object result = method.invoke(obj, 1, 4);
System.out.println(result);  // 输出: 5

# 4、动态操作字段

// 获取Class对象
Class<?> clazz = Class.forName("reflect.Student");
Student st = (Student) clazz.getDeclaredConstructor().newInstance();

// 获取public字段
Field ageField = clazz.getField("age");
ageField.set(st, 18);

// 获取private字段(需要设置accessible)
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true);  // 突破访问权限
nameField.set(st, "张三");

# 5、反射的性能优化

反射操作比直接调用慢,但可以通过以下方式优化:

  1. 缓存反射对象:将 Method、Field 等对象缓存起来重复使用
  2. 使用 setAccessible(true):跳过访问权限检查
  3. 使用 MethodHandle:Java 7 引入的更高效的方法调用机制

# 6、vs 反射

Java 7 引入了 java.lang.invoke.MethodHandle,相比传统反射有以下优势:

  • 性能更好:接近直接调用的性能
  • 类型安全:编译时类型检查
  • 更灵活:支持方法的组合和变换
// MethodHandle示例
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(int.class, int.class, int.class);
MethodHandle mh = lookup.findVirtual(MethodClass.class, "add", mt);
int result = (int) mh.invoke(new MethodClass(), 1, 4);

更多细节请参考:反射机制详解 (opens new window) 和 Method Handles in Java (opens new window)

# 四、动态代理

动态代理是在运行时动态创建代理类和代理对象的技术,相比静态代理,它不需要为每个目标类手动编写代理类,大大提高了开发效率。Java提供了两种主要的动态代理实现方式。

# 1、JDK动态代理

基于接口的动态代理,要求目标类必须实现接口。核心类:

  • java.lang.reflect.Proxy:用于创建代理对象
  • java.lang.reflect.InvocationHandler:定义代理逻辑

示例:动态代理 IUserDao 接口

public interface IUserDao {
    void save();
    
    User findById();
}

public class ProxyFactory {

    private Class<?> targetClass;

    public ProxyFactory(Class<?> targetClass) {
        this.targetClass = targetClass;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(targetClass.getClassLoader(), new Class[] {targetClass},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName() == "save"){
                            System.out.println("save method");
                        } else if (method.getName() == "findById") {
                            return new User();   
                        }
                        return null;
                    }
                });
    }
}

public class TestProxy {

    @Test
    public void testDynamicProxy() {
        IUserDao proxy = (IUserDao) new ProxyFactory(IUserDao.class).getProxyInstance();
        System.out.println(proxy.getClass());  // 输出: class com.sun.proxy.$Proxy0
        proxy.save();  // 输出: save method
        System.out.println(proxy.findById());  // 输出: User对象
    }
}

# 2、动态代理的应用场景

  1. AOP编程:日志记录、事务管理、权限控制
  2. RPC框架:如 Dubbo、gRPC 的客户端代理
  3. ORM框架:如 MyBatis 的 Mapper 接口代理
  4. Mock测试:如 Mockito 框架
  5. 懒加载:延迟初始化大对象

更多细节请参考:Java代理模式 (opens new window)

# 五、字节码生成

字节码生成技术允许我们在运行时直接操作和生成 JVM 字节码,这是实现许多高级框架功能的基础技术。

# 1、字节码操作框架对比

框架 特点 学习曲线 性能 使用场景
ASM 最底层、最灵活 陡峭 最高 需要极致性能和控制
Javassist 源码级API 平缓 中等 简单的字节码修改
CGLIB 基于ASM的高层封装 平缓 高 动态代理、AOP
ByteBuddy 现代化、类型安全 适中 高 复杂的字节码生成

# 2、ASM框架

ASM是最底层的字节码操作框架,直接操作字节码指令:

  • 优点:性能最高、控制最精细
  • 缺点:需要理解JVM字节码指令、API复杂
  • 应用:Spring、Hibernate等框架的底层实现

详细教程:简易ASM教程 (opens new window)

# 3、CGLIB动态代理

CGLIB(Code Generation Library)基于ASM实现,可以代理普通类(不仅限于接口):

public class UserDao{

    public void save() {
        System.out.println("保存数据");
    }
}

public class ProxyFactory implements MethodInterceptor{

    private Object target;//维护一个目标对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //为目标对象生成代理对象
    public Object getProxyInstance() {
        //工具类
        Enhancer en = new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类对象代理
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开启事务");
        // 执行目标对象的方法
        Object returnValue = method.invoke(target, args);
        System.out.println("关闭事务");
        return null;
    }
}

public class TestProxy {

    @Test
    public void testCglibProxy() {
        // 目标对象
        UserDao target = new UserDao();
        System.out.println(target.getClass());  // 输出: class UserDao
        // 代理对象
        UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
        System.out.println(proxy.getClass());  // 输出: class UserDao$$EnhancerByCGLIB$$xxx
        // 执行代理对象方法
        proxy.save();  // 输出: 开启事务 -> 保存数据 -> 关闭事务
    }
}

CGLIB的工作原理:

  1. 通过 Enhancer 类动态生成目标类的子类
  2. 覆写父类的非 final 方法
  3. 通过 MethodInterceptor 拦截方法调用
  4. 底层使用 ASM 框架生成字节码

CGLIB vs JDK动态代理:

  • JDK动态代理:基于接口,使用反射,适合接口代理
  • CGLIB:基于继承,使用字节码生成,可代理普通类,性能更高

# 4、字节码生成 vs javac编译器

虽然 javac 编译器也能生成字节码,但字节码生成库有其独特优势:

对比维度 javac编译器 字节码生成库
工作时机 编译期(静态) 运行期(动态)
输入形式 Java源代码文件 API调用
灵活性 受Java语法限制 可操作任意字节码指令
性能 需要启动进程、文件I/O 内存操作,更高效
使用场景 静态编译 动态生成、修改类

为什么需要字节码生成库:

  1. 运行时动态性:无需源码,直接在内存中生成类
  2. 突破语法限制:可生成Java语法无法表达的字节码
  3. 性能优势:避免了编译器启动和文件I/O开销
  4. 细粒度控制:可精确控制字节码的每个细节

# 5、22 新特性:ClassFile API(预览)

Java 22 引入了官方的 ClassFile API(JEP 457),这是一个重要的里程碑,标志着Java平台开始提供原生的字节码操作支持。

为什么需要 ClassFile API:

  • 版本兼容性:第三方库(ASM、ByteBuddy)可能跟不上Java的快速迭代(6个月一版)
  • 标准化:提供统一的官方API,减少对第三方库的依赖
  • 性能优化:作为JDK的一部分,可以更好地与JVM集成

ClassFile API 的核心功能:

  1. 解析(Parse):读取和分析现有的 .class 文件
  2. 生成(Generate):从零开始创建新的类文件
  3. 转换(Transform):修改现有类文件并重新生成

使用示例:

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.lang.classfile.*;  // Java 22+ 预览特性

public class ClassFileDemo {
    public static void main(String[] args) throws IOException {
        // 解析现有类文件
        Path classFilePath = Paths.get("MyClass.class");
        ClassModel classModel = ClassFile.of().parse(classFilePath);
        
        // 获取类的基本信息
        System.out.println("类名: " + classModel.thisClass().name());
        System.out.println("父类: " + classModel.superclass().name());
        System.out.println("版本: " + classModel.majorVersion());
        
        // 遍历字段和方法
        classModel.fields().forEach(field -> 
            System.out.println("字段: " + field.fieldName()));
        
        classModel.methods().forEach(method -> 
            System.out.println("方法: " + method.methodName()));
        
        // 转换类文件(添加日志)
        byte[] newBytes = ClassFile.of().transform(classModel, 
            ClassTransform.transformingMethods(
                method -> method.methodName().equals("targetMethod"),
                MethodTransform.ofCode(codeBuilder -> {
                    // 在方法开始处添加日志代码
                    codeBuilder.getstatic(/*...*/);
                    codeBuilder.ldc("Method called");
                    codeBuilder.invokevirtual(/*...*/);
                })
            )
        );
    }
}

注意:ClassFile API 目前是预览特性,需要使用 --enable-preview 参数启用。

更多详情:Java 22: Class-File API (opens new window)

# 六、AOP(面向切面编程)

AOP(Aspect Oriented Programming)是对OOP(面向对象编程)的补充,它提供了一种将横切关注点(如日志、事务、安全)与业务逻辑分离的编程范式。

# 1、AOP的核心概念

  • 切面(Aspect):横切关注点的模块化
  • 连接点(Join Point):程序执行的某个位置,如方法调用
  • 切入点(Pointcut):匹配连接点的表达式
  • 通知(Advice):在切入点执行的动作
  • 织入(Weaving):将切面应用到目标对象的过程

# 2、AOP 示例

@Component
@Aspect
public class LoggingAspect {
    
    // 前置通知:方法执行前记录日志
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        String method = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        log.info("调用方法: {} 参数: {}", method, Arrays.toString(args));
    }
    
    // 环绕通知:记录方法执行时间
    @Around("@annotation(Timed)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long duration = System.currentTimeMillis() - start;
        log.info("方法 {} 执行耗时: {}ms", 
                 joinPoint.getSignature().getName(), duration);
        return result;
    }
    
    // 异常通知:记录异常信息
    @AfterThrowing(pointcut = "execution(* com.example..*(..))", 
                   throwing = "ex")
    public void logException(JoinPoint joinPoint, Exception ex) {
        log.error("方法 {} 抛出异常: {}", 
                  joinPoint.getSignature().getName(), ex.getMessage());
    }
}

# 3、AOP的实现方式

  1. 编译时织入:AspectJ编译器,在编译期修改字节码
  2. 类加载时织入:通过特殊的类加载器,在类加载时修改字节码
  3. 运行时织入:Spring AOP,使用动态代理(JDK或CGLIB)

# 4、AOP的典型应用场景

  • 日志记录:统一的日志处理
  • 事务管理:声明式事务 @Transactional
  • 权限控制:方法级别的权限检查
  • 性能监控:方法执行时间统计
  • 缓存管理:@Cacheable 注解
  • 异常处理:统一的异常捕获和处理

详细文档:Spring AOP 官方文档 (opens new window)

# 七、Agent

Java Agent 是JVM提供的一种强大机制,允许在JVM启动时或运行时动态修改字节码,实现无侵入式的功能增强。

# 1、Agent 的工作原理

Java Agent 基于 JVMTI(JVM Tool Interface)和 Instrumentation API:

  • JVMTI:JVM提供的native编程接口
  • Instrumentation:Java层面的字节码操作API
  • ClassFileTransformer:字节码转换器接口

# 2、两种加载方式

  1. 静态加载(premain):JVM启动时通过 -javaagent 参数加载
  2. 动态加载(agentmain):JVM运行时通过 Attach API 加载

# 3、示例:监控类加载

public class PreMainTraceAgent {
    
    // JVM启动时调用
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("Agent参数: " + agentArgs);
        inst.addTransformer(new ClassLogger(), true);
    }
    
    // 类文件转换器
    static class ClassLogger implements ClassFileTransformer {
        @Override
        public byte[] transform(ClassLoader loader, 
                               String className,
                               Class<?> classBeingRedefined,
                               ProtectionDomain protectionDomain,
                               byte[] classfileBuffer) {
            // 记录加载的类
            if (className != null && className.startsWith("com/example")) {
                System.out.println("加载类: " + className.replace('/', '.'));
                // 这里可以使用ASM等工具修改字节码
            }
            return classfileBuffer;  // 返回原始或修改后的字节码
        }
    }
}

打包配置(MANIFEST.MF):

Manifest-Version: 1.0
Premain-Class: com.example.PreMainTraceAgent
Agent-Class: com.example.PreMainTraceAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

使用方式:

# 静态加载
java -javaagent:agent.jar=参数 MainClass

# 动态加载(需要使用Attach API)
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent("agent.jar", "参数");
vm.detach();

# 4、Agent 的实际应用

# 4.1、APM(应用性能监控)

  • Arthas (opens new window):阿里开源的Java诊断工具

    • 实时查看JVM状态、线程堆栈
    • 动态修改日志级别
    • 方法执行监控和热修复
  • SkyWalking (opens new window):分布式追踪系统

    • 自动探针,无侵入式监控
    • 分布式调用链追踪
    • 性能指标收集

# 4.2、开发工具

  • JRebel:热部署工具,修改代码无需重启
  • Lombok:编译时代码生成(使用注解处理器)
  • Mockito:单元测试Mock框架

# 4.3、字节码增强示例

// 使用ByteBuddy在Agent中增强类
public static void premain(String args, Instrumentation inst) {
    new AgentBuilder.Default()
        .type(ElementMatchers.nameStartsWith("com.example"))
        .transform((builder, type, classLoader, module) ->
            builder.method(ElementMatchers.any())
                   .intercept(MethodDelegation.to(TimingInterceptor.class))
        )
        .installOn(inst);
}

public class TimingInterceptor {
    @RuntimeType
    public static Object intercept(@Origin Method method,
                                  @AllArguments Object[] args,
                                  @SuperCall Callable<?> callable) throws Exception {
        long start = System.currentTimeMillis();
        try {
            return callable.call();
        } finally {
            System.out.println(method.getName() + " 耗时: " + 
                             (System.currentTimeMillis() - start) + "ms");
        }
    }
}

更多细节:

  • Java 动态调试技术原理及实践 (opens new window)
  • javaagent使用指南 (opens new window)

# 八、总结

本文深入探讨了Java运行期的六大动态能力,它们构成了一个完整的技术体系:

# 1、技术关系图谱

类加载器(基础)
    ↓
反射 + 动态代理(API层)
    ↓
字节码生成(底层支撑)
    ↓
AOP(设计模式)
    ↓
Java Agent(JVM级增强)

# 2、核心要点

  1. 层次递进:从类加载器的基础机制,到反射和动态代理的API支持,再到字节码生成的底层实现,形成了完整的技术栈。

  2. 相互依赖:

    • 动态代理依赖反射机制
    • CGLIB依赖字节码生成(ASM)
    • AOP建立在动态代理之上
    • Java Agent结合字节码生成实现功能增强
  3. 实践价值:

    • 框架开发:Spring、Hibernate等框架大量使用这些技术
    • 中间件:RPC框架、ORM框架的核心实现
    • 开发工具:热部署、性能监控、调试工具
    • 架构设计:插件化、模块化系统设计

# 3、技术选型建议

场景 推荐技术 原因
简单对象创建 反射 API简单,满足基本需求
接口代理 JDK动态代理 原生支持,无需依赖
类代理 CGLIB 成熟稳定,Spring默认选择
复杂字节码操作 ByteBuddy 现代化API,类型安全
横切关注点 Spring AOP 声明式编程,易于维护
生产监控 Java Agent 无侵入,动态加载

# 4、未来展望

随着Java的持续演进,运行期动态能力也在不断增强:

  • ClassFile API(Java 22+):官方字节码操作支持
  • Project Loom:虚拟线程带来的新可能
  • GraalVM:AOT编译与动态能力的平衡

掌握这些动态能力,不仅能让我们更好地理解Java生态中各种框架的实现原理,还能在实际开发中选择最合适的技术方案,构建更加灵活、可维护的系统。

祝你变得更强!

编辑 (opens new window)
#Java动态能力
上次更新: 2025/08/15
Java 网络编程
Java可插入注解处理器

← Java 网络编程 Java可插入注解处理器→

最近更新
01
AI时代的编程心得
09-11
02
Claude Code与Codex的协同工作
09-01
03
Claude Code实战之供应商切换工具
08-18
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式