文章阐述了JVM的分代垃圾回收策略:新生代使用复制算法,老年代采用标记‑清除或标记‑整理。分别介绍了Serial、Parallel、ParNew 与 CMS 四种收集器的实现原理和适用场景,重点说明 ParNew 可与 CMS 配合实现低停顿的并发回收,并列出 CMS 的关键参数配置。随后深入剖析 CMS 并发标记过程中的三色标记模型、写屏障、浮动垃圾与漏标问题,以及增量更新和 SATB 两种解决方案,帮助读者理解底层实现细节并进行针对性调优。

文章演示了在 Java 中获取 Class 对象的多种方式。首先通过实例调用 getClass() 获得运行时类;其次使用 Class.forName("完整类名") 根据类全路径加载;再次直接使用类字面量 ClassName.class 获取;对于基本类型包装类,可通过其 TYPE 字段得到对应的 Class;最后可通过 Class 的 getSuperclass() 方法获取父类的 Class 对象。文中通过 Student 与其父类 Person 的示例代码,分别展示了上述方法的调用及其输出结果,说明不同获取方式返回的 Class 对象在 hashCode 上相等,且 TYPE 是通过内部的 getPrimitiveClass 实现的。

文章系统梳理了JVM常见垃圾收集器的特性与适用场景。Serial 为单线程收集器,适用于Client模式新生代;ParNew 为其多线程版,可与CMS配合使用;Parallel Scavenge 与 Parallel Old 侧重吞吐量,适合多CPU服务器环境;CMS 采用并发标记‑清除,追求最短停顿但易产生碎片并对CPU敏感;G1 通过分区回收实现可预测停顿,提供简单的调优参数(如‑XX:MaxGCPauseMillis)。整体上,选择哪种收集器取决于对停顿时长、吞吐量和硬件资源的需求。

桥接方法是 JDK 1.5 为保持泛型字节码与旧版兼容而由编译器自动生成的合成方法,可通过 `Method.isBridge()` 或 ACC_BRIDGE/ACC_SYNTHETIC 标志识别。它在以下情况下产生:实现带泛型的接口(如 `Consumer<T>`、`Supplier<T>`、`Function<T,R>`)时,编译器会生成返回 `Object` 或接受 `Object` 的桥接方法;子类覆盖父类方法且返回类型协变(子类返回更具体的类型)时亦会生成。参数类型、访问修饰符升级、静态方法等不会触发桥接。产生桥接的目的是在泛型擦除后仍能保持方法签名兼容,避免运行时类型错误。

类型擦除是 Java 泛型在编译后被抹去的机制。JDK 1.5 引入的泛型信息仅存在于编译阶段,进入 JVM 前所有泛型参数都会被替换:若未指定上限,则替换为 `Object`;若有上限(如 `T extends CharSequence`),则替换为上限类型。示例中 `Message<String>` 与 `Message<Integer>` 在运行时得到同一类 `Message`,`Point2<T>` 的字段在运行时为 `Object`,而 `Point6<T extends CharSequence>` 的字段为 `CharSequence`。由于类型擦除,编译期的类型检查在运行时失效,利用反射可以向泛型容器中插入不匹配的对象,演示了“伪泛型”的特性。

PECS(Producer Extends, Consumer Super)是 Java 泛型的使用准则。`? extends T` 表示生产者,只能读取 T 或其子类,写入全部被禁止;`? super T` 表示消费者,只能写入 T 或其子类,读取只能得到 Object。示例中 `List<? extends Fruit>` 只能取 Fruit,`List<? super Fruit>` 只能放入 Fruit 或 Apple。数组在 Java 中是协变的,Kotlin 用 `out`/`in` 表示同义的协变/逆变,并通过 `inline reified` 实现运行时泛型实化。若集合既要写又要读,则不应使用通配符。