本文系统阐述JVM分代垃圾回收原理,比较复制、标记‑清除、标记‑整理三大算法,并逐一介绍Serial、Parallel Scavenge、ParNew、CMS四种收集器的实现机制、适用场景及关键参数。以电商订单系统为例,演示ParNew+CMS的调优方案,包括堆结构、对象年龄阈值和老年代触发阈值的配置。随后深入解析CMS并发标记使用的三色标记模型,说明浮动垃圾、漏标问题及写屏障(增量更新、SATB)的实现细节。全文聚焦提升吞吐量、降低停顿的权衡与实践技巧。

文章演示了获取Java中Class对象的五种常用方式:①通过实例调用getClass();②使用Class.forName()并传入完整类名;③直接使用类名.class语法;④对基本类型的包装类使用TYPE属性获取对应的Class;⑤通过已有Class对象的getSuperclass()获取父类Class。示例代码以Student和其父类Person为例,分别打印了Class对象的hashCode或名称,说明这些方法返回的Class实例在同一类型时相同。

Serial收集器是单线程、停顿式的最早新生代GC,适用于Client模式小内存场景;ParNew是其多线程版,可配合CMS使用;Parallel Scavenge 采用复制算法并行回收,侧重吞吐量,可通过‑XX:GCTimeRatio、‑XX:MaxGCPauseMillis 调节;Serial Old 与 Parallel Old 分别是对应的老年代单/多线程标记‑整理收集器,前者在Client或CMS 失败时使用,后者与 Parallel Scavenge 组合实现高吞吐;CMS 采用标记‑清除并发执行,目标最短停顿,但对 CPU 敏感且产生碎片;G1 以易调优为设计目标,支持‑XX:+UseG1GC、‑XX:MaxGCPauseMillis 等参数,实现可控停顿和混合回收。

桥接方法是 JDK 1.5 引入泛型后,为保持新旧字节码兼容而由编译器自动生成的合成方法,字节码中标记为 ACC_BRIDGE 与 ACC_SYNTHETIC,可通过 Method.isBridge() 判断。产生情形主要有两种:①实现带泛型的接口(如 Consumer<T>、Supplier<T>、Function<T,R>),编译后会生成返回 Object 或接受 Object 的桥接方法;②在子类覆盖父类方法并升级返回类型(协变返回),编译器同样生成桥接方法。参数类型、访问修饰符的改变以及静态方法均不会产生桥接方法。桥接方法的作用是弥补泛型擦除后方法签名的差异,保证运行时多态行为与编译期类型检查的一致性,从而实现向前兼容。

Java 在 JDK 1.5 引入泛型,但所有泛型信息仅在编译期存在,进入 JVM 前会被擦除,称为类型擦除。擦除后,不同类型参数的实例在运行时是同一个原始类(如 `Message<String>` 与 `Message<Integer>` 的 `Class` 相同),类的字段会被替换为 `Object`,若声明了上限则替换为上限类型(如 `T extends CharSequence` 变为 `CharSequence`)。因此 Java 泛型是“伪泛型”。通过反射调用原始 `Object` 方法,可以在运行时向本应受限的集合中插入不匹配的元素,绕过编译期检查。

PECS(Producer Extends, Consumer Super)是 Java 泛型中处理协变与逆变的规则。使用 `? extends T` 表示只能从集合读取 T 或其子类元素,写入全部被禁止;使用 `? super T` 表示只能向集合写入 T 或其子类元素,读取只能得到 Object。示例代码说明了两种通配符在赋值、添加和读取时的编译行为,并比较了 Kotlin 的 `out`/`in` 与 Java 的实现差异。还指出数组在 Java 中是协变的,以及 Kotlin 通过 `inline reified` 实现的泛型实化。总结:读取用 `extends`,写入用 `super`,若需兼顾两者则不使用通配符。