1.JVM 类加载:Java 程序的「启动与运作密码」

20 阅读3分钟

一、类的生命周期:从诞生到退场的 5 步旅程

类的 “一生” 要经历加载、连接、初始化、使用、卸载,其中连接是 “安检环节”,包含验证、准备、解析三步。特别注意:解析阶段像 “灵活的安检项”,不一定按顺序来,可在初始化后启动。

二、类加载过程:5 步搭建运行基础​

  1. 加载:如同 “寻宝”,按路径找到 class 文件并导入 JVM。​
  1. 验证:好比 “质检”,检查 class 文件是否符合 JVM 规范,杜绝 “不合格品”。​
  1. 准备:给类的静态变量 “分配房间”(内存),并设好默认初始值。​
  1. 解析:把常量池里的 “符号名片”(符号引用)换成 “实际地址”(直接引用),让 JVM 能精准找到资源。​
  1. 初始化:为静态变量赋真实值、执行静态代码块,给类 “激活生命力”。​

三、初始化顺序:严格的 “启动流程”​

必须按以下顺序执行,像按步骤组装机器:​

  1. 父类静态成员→父类静态代码块​
  1. 子类静态成员→子类静态代码块​
  1. 父类实例变量→父类非静态代码块→父类构造函数​
  1. 子类实例变量→子类非静态代码块→子类构造函数​

四、触发初始化:6 种 “启动信号”​

出现以下情况,类会被 “唤醒” 初始化:​

  • 用new创建对象,好比 “召唤” 类的实例​
  • 访问 / 修改类 / 接口的静态变量,或调用静态方法​
  • 反射加载(如Class.forName),像 “远程唤醒”​
  • 初始化子类时,先 “唤醒” 父类(父类优先)​
  • 虚拟机启动时,启动类(含main方法)自动初始化​

五、类加载器:类的 “专属搬运工”​

类在 JVM 中的唯一性,由 “搬运工”(类加载器)和类本身共同决定,每个 “搬运工” 有独立 “仓库”(类名称空间)。主要分 4 类:​

  1. 启动类加载器:搬运 Java 安装目录lib下的核心类库,是 “顶层搬运工”。​
  1. 扩展类加载器:搬运lib\ext或系统变量指定路径的类库,负责 “扩展资源”。​
  1. 应用程序类加载器:搬运ClassPath下的类,是默认 “搬运工”,可直接调用。​
  1. 自定义类加载器:应对特殊场景(如加载加密 class),按需定制 “专属搬运工”。​

六、类加载机制:3 条 “工作规则”​

  1. 全盘负责:“搬运工” 加载一个类时,顺带搬运该类依赖的其他类,除非指定其他 “搬运工”。​
  1. 父类委托:“搬运工” 收到任务,先交给父 “搬运工” 尝试,父类办不到才自己上,避免重复劳动。​
  1. 缓存机制:加载过的类会存入 “缓存仓库”,下次用先查缓存,没找到再重新加载 —— 这就是修改 Class 后需重启 JVM 的原因。​

七、双亲委派:“层层上报” 的安全机制​

“搬运工” 收到加载请求,先委托父 “搬运工”,依次向上到启动类加载器。只有父类 “找不到”,子类才自己加载。比如应用程序类加载器加载类时:​

应用类加载器→扩展类加载器→启动类加载器(失败)→扩展类加载器(失败)→应用类加载器(加载),失败则抛ClassNotFoundException。​

自定义类加载器时,建议重写findClass方法,别改loadClass,避免破坏这套 “安全规则”。​

八、为何需要父类委托?2 大核心原因​

  1. 避免重复加载:不同 “搬运工” 不会重复加载同一类,节省内存。​
  1. 保障安全:核心类由顶层 “搬运工” 加载,防止恶意类篡改核心逻辑。