1. 类初始化和类加载
1.1 创建对象的过程
在 JVM 中,创建一个新对象大致经历四个关键步骤:类加载检查、分配内存空间、初始化零值操作、进行必要设置(对象头),最后执行构造方法。
类加载:当虚拟机遇到 new 关键字时,会先检查对应类是否已加载。若未加载,则优先执行类加载流程,随后才继续执行 new 操作。
分配内存空间:在堆内存中为对象开辟一段连续的空间。
初始化零值操作:将对象实例变量初始化为默认零值(对象头信息除外)。
进行必要的设置:例如给对象头写入类的元数据、对象的哈希码、分代年龄等信息。
执行构造方法:调用对应的 <init> 方法完成对象初始化。
1.2 对象的生命周期
对象的生命周期主要包含三个阶段:创建、使用、销毁。
- 创建:即上述的实例化过程。
- 使用:通过引用访问该对象的成员或方法。
- 销毁:当对象不再被任何路径可达的引用链指向时,会被标记为垃圾并回收。
1.3 类加载器
JVM 内置了三种类加载器:
- 启动类加载器 (Bootstrap):负责加载 Java 核心库中的类,通常由 C++ 实现。
- 扩展类加载器 (Extension):负责加载扩展目录下的类,如框架提供的类。
- 应用程序类加载器 (Application):负责加载用户自定义的类,是默认的类加载器。
1.4 双亲委派模型
双亲委派模型遵循'向上委派,向下加载'的原则。当一个类加载器收到加载请求时,不会立即尝试自己加载,而是先将请求委派给父类加载器。依次类推,直到委派给最顶层的启动类加载器。如果父加载器无法加载,子类才会尝试自己加载。
这种机制主要有以下作用:
- 保证类的唯一性:确保一个类只会被一个类加载器加载一次,避免重复加载。
- 保证安全性:防止用户自定义的类(如
java.lang.String)覆盖核心库类,保护系统安全。 - 形成隔离和分层:不同层级的加载器负责不同范围的类,既高效又清晰。
- 简化加载流程:统一的委派机制减少了类加载逻辑的复杂度。
1.5 类加载的过程
从宏观上看,类加载分为五个阶段:加载、连接、初始化、使用、卸载。其中连接阶段可细分为验证、准备和解析,因此微观上常称为七个步骤。
- 加载:通过全限定名找到二进制字节码文件,将其转换为方法区内的运行时数据结构。
- 验证:确保字节码符合 JVM 规范,包括文件格式校验、元数据验证、字节码验证等。
- 准备:为类的静态变量分配内存并设置默认初始值。
- 解析:将常量池内的符号引用替换为直接引用。
- 初始化:执行类构造器
<clinit>方法,处理父类和子类的静态成员及静态代码块。 - 使用:程序运行期间对类进行操作。
- 卸载:当类的所有实例被回收、类加载器被回收且该类未被引用时,可被卸载。
2. 垃圾回收
2.1 垃圾回收介绍
传统开发需要手动管理内存释放,而垃圾回收(GC)机制能自动回收无用内存。这不仅提高了开发效率,也有效避免了内存溢出和内存泄漏等问题。
2.2 触发垃圾回收的方式
GC 触发通常有以下几种情况:
- 内存不足:当堆内存无法满足新对象分配需求时触发。
- 手动执行:开发人员可通过
System.gc()建议 JVM 执行 GC(不保证立即执行)。 - JVM 调参:通过参数配置调整 GC 行为。
- 内部策略:GC 器根据对象创建频率、内存使用情况等阈值自动触发。
2.3 判断垃圾的方法
主流算法有两种:
- 引用计数法:每个对象维护一个计数器,引用次数为 0 时判定为垃圾。缺点是难以解决循环引用问题。
- 可达性分析法:从 GC Roots 出发向下搜索,未被标记的对象即为垃圾。常见的 GC Roots 包括:Java 核心库类、本地方法栈引用、活跃线程等。
2.4 垃圾回收算法
常见的回收算法包括:
- 标记清除算法:标记所有存活对象后清除未标记对象。优点是速度快,缺点是会产生大量内存碎片。
- 标记整理算法:标记后移动存活对象以紧凑内存。优点是无碎片,缺点是移动对象开销大。
- 复制算法:将内存分为两份,交替使用。优点是效率高无碎片,缺点是内存利用率较低。
2.5 垃圾回收器
根据不同区域和特性,收集器有所区别:
- 新生代:Serial、ParNew、Parallel Scavenge,多采用复制算法。
- 老年代:Serial Old(标记整理)、CMS(标记清除)、Parallel Old(标记整理)。
- 整个堆:G1,整体采用标记整理,细分区域结合复制算法。
Serial 为串行收集器;ParNew/CMS 侧重响应时间;Parallel GC 侧重吞吐量;G1 则在两者间取得平衡。
2.6 minorGC、majorGC、fullGC
- minorGC:作用于新生代。当 Eden 区空间不足时触发,存活对象年龄加一。特点是频繁但耗时短。
- majorGC:作用于老年代。当对象晋升老年代失败时触发。特点是次数少,耗时较长。
- fullGC:作用于整个堆。通常因 Minor GC 后老年代仍不足触发,涉及全局清理。特点是耗时最长,应尽量避免。
2.7 CMS 与 G1 的区别
| 方面 | CMS | G1 |
|---|---|---|
| 作用范围 | 主要针对老年代 | 作用于整个堆 |
| STW 时间 | 较短,追求低延迟 | 可预测,支持时间控制 |
| 内存碎片 | 使用标记清除,易产生碎片 | 使用分区整理,基本无碎片 |
| 回收过程 | 初始标记、并发标记、重新标记、并发清理 | 初始标记、并发标记、最终标记、筛选回收 |
| 浮动垃圾 | 存在,需预留空间 | 较少,效率更高 |
CMS 采用并发清理,若垃圾产生速度过快可能导致性能下降;G1 通过多个回收器并行工作,更适合大内存场景。


