JVM垃圾收集器旨在优化内存回收,主要包括Serial、Parallel Scavenge、ParNew和CMS等。分代收集理论是基础,根据对象存活周期将内存划分为新生代和老年代,并选择合适的回收算法——新生代多用复制算法,老年代则采用标记-清除或标记-整理算法。 Serial收集器是单线程的,简单高效但会暂停所有工作线程(Stop The World)。Parallel Scavenge关注吞吐量,采用多线程并行回收。ParNew是Parallel收集器的变种,可与CMS配合使用。CMS追求低停顿时间,采用并发标记-清除算法,但对CPU敏感且可能产生浮动垃圾和空间碎片。 底层实现中,三色标记法用于并发标记阶段,区分黑色(已扫描)、灰色(部分扫描)和白色(未扫描)对象,以避免漏标或多标。写屏障技术用于解决并发标记期间的引用变化,确保回收的准确性。 选择垃圾收集器并非追求“最好”,而是根据应用场景进行权衡。例如,在高并发、低延迟的场景下,ParNew+CMS可能是较优选择。文章以亿级流量电商系统为例,提供了JVM参数调整建议,包括堆大小、新生代比例、对象年龄阈值等,以优化垃圾回收性能。

本文介绍了获取Java类Class对象(用于反射机制)的五种常用方式。首先,可以通过已存在的对象实例调用`getClass()`方法获取其Class对象。其次,可以使用`Class.forName("类全路径")`通过类名字符串获取Class对象。第三,可以直接通过类名后接`.class`获取,例如`Student.class`。第四,对于基本内置类型,可以使用包装类的`TYPE`属性获取对应的Class对象,例如`Integer.TYPE`。最后,可以通过已知的Class对象调用`getSuperclass()`方法获取其父类的Class对象。文章通过代码示例展示了每种方式的具体实现,并输出了Class对象的hashCode值,验证了获取方式的有效性。

本文详细介绍了JVM主要垃圾收集器,包括Serial(单线程,Client模式默认)、ParNew(Serial多线程版本,Server模式首选)、Parallel Scavenge(吞吐量优先,自适应策略)、Serial Old(Serial老年代版本)、Parallel Old(Parallel Scavenge老年代版本)、CMS(并发标记清除,低停顿)和G1(可预测停顿,简单调优)。各收集器针对不同场景优化:Serial适合小内存应用,ParNew与CMS配合,Parallel追求高吞吐,CMS关注低停顿,G1提供统一内存管理和可调优停顿时间。

桥接方法是JDK 1.5引入泛型后,为了保持与旧版本字节码的兼容性,由编译器自动生成的方法。可以通过`Method.isBridge()`判断一个方法是否为桥接方法,其字节码会被标记为`ACC_BRIDGE`和`ACC_SYNTHETIC`。 桥接方法主要在以下几种情况产生:1) 实现泛型接口(如`Consumer<T>`、`Supplier<T>`、`Function<T,R>`);2) 子类覆盖超类方法并升级返回类型;3) 静态方法不会生成桥接方法;4) 升级访问修饰符不会生成桥接方法。 生成桥接方法的核心原因是Java泛型的类型擦除机制。为了在编译时移除泛型信息,保证与旧版本代码的兼容性,编译器会生成桥接方法来处理类型转换和方法调用,尽管运行时实际执行的是原始类型的方法,但桥接方法在类型检查时可能抛出异常。总而言之,桥接方法的存在是为了保证泛型代码在不同Java版本之间的兼容性。

Java泛型虽然在代码中提供了类型检查,但实际上是一种“伪泛型”。这是因为Java的泛型信息在编译阶段会被擦除,即所谓的“类型擦除”。这意味着在JVM运行时,泛型类和普通类并没有区别。 具体表现为:泛型类实例的类型始终相同,即使泛型参数不同;泛型字段在擦除后类型变为`Object`,或者如果指定了类型上限,则变为类型上限;通过反射可以绕过编译时类型检查,向泛型集合中添加不符合泛型声明的类型。 类型擦除使得Java泛型主要用于编译时提供类型安全,避免了运行时类型转换的开销,但也带来了一些限制,例如无法在运行时获取泛型类型信息。文章通过多个例子,详细说明了类型擦除的原理和影响。