JVM加载机制是什么

发布时间:2021-06-18 17:52:42 作者:chen
来源:亿速云 阅读:152
# JVM加载机制是什么

## 前言

Java虚拟机(JVM)作为Java语言的核心运行环境,其类加载机制是理解Java程序运行原理的关键。本文将深入剖析JVM类加载的全过程,包括加载、验证、准备、解析、初始化等阶段,并探讨双亲委派模型、自定义类加载器等高级主题。

---

## 目录
1. [类加载的基本概念](#一-类加载的基本概念)
2. [类加载的详细过程](#二-类加载的详细过程)
   - 2.1 [加载阶段](#21-加载阶段)
   - 2.2 [验证阶段](#22-验证阶段)
   - 2.3 [准备阶段](#23-准备阶段)
   - 2.4 [解析阶段](#24-解析阶段)
   - 2.5 [初始化阶段](#25-初始化阶段)
3. [类加载器体系](#三-类加载器体系)
   - 3.1 [双亲委派模型](#31-双亲委派模型)
   - 3.2 [破坏双亲委派](#32-破坏双亲委派)
4. [自定义类加载器](#四-自定义类加载器)
5. [实际应用场景](#五-实际应用场景)
6. [常见面试题解析](#六-常见面试题解析)
7. [总结与展望](#七-总结与展望)

---

## 一、类加载的基本概念

### 1.1 什么是类加载
类加载是指将.class文件中的二进制数据读入到内存中,将其放在方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

### 1.2 类加载的时机
JVM规范严格规定了有且只有以下五种情况必须立即对类进行初始化(而加载、验证、准备自然需要在此之前完成):
- 遇到new、getstatic、putstatic或invokestatic这四条字节码指令时
- 使用java.lang.reflect包的方法对类进行反射调用时
- 当初始化一个类时,发现其父类还未初始化时
- 虚拟机启动时,用户指定的主类(包含main()方法的类)
- JDK7动态语言支持时的方法句柄解析结果REF_getStatic等

---

## 二、类加载的详细过程

### 2.1 加载阶段
加载阶段完成以下三件事:
1. 通过类的全限定名获取定义此类的二进制字节流
2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
3. 在内存中生成一个代表该类的Class对象,作为方法区这个类的各种数据的访问入口

**示例代码:**
```java
public class LoaderDemo {
    public static void main(String[] args) {
        System.out.println("Class loading example");
    }
}

2.2 验证阶段

验证阶段包括四个检验动作: 1. 文件格式验证(魔数、版本号等) 2. 元数据验证(语义分析) 3. 字节码验证(栈映射帧) 4. 符号引用验证(常量池解析)

2.3 准备阶段

正式为类变量(static变量)分配内存并设置初始值(零值)。注意: - 这时候进行内存分配的仅包括类变量 - 如果类字段是final static,则直接赋值为定义值

2.4 解析阶段

将常量池内的符号引用替换为直接引用的过程,主要针对: - 类或接口 - 字段 - 类方法 - 接口方法 - 方法类型 - 方法句柄 - 调用点限定符

2.5 初始化阶段

执行类构造器<clinit>()方法的过程,该方法: - 由编译器自动收集类中所有类变量的赋值动作和静态语句块合并产生 - 虚拟机会保证子类的<clinit>()执行前父类的<clinit>()已经执行完毕


三、类加载器体系

3.1 双亲委派模型

类加载器的层次结构: 1. Bootstrap ClassLoader:加载/lib目录下的核心类 2. Extension ClassLoader:加载/lib/ext目录的扩展类 3. Application ClassLoader:加载用户类路径(ClassPath)上的类

工作流程图示:

graph TD
    A[自定义类加载器] --> B[AppClassLoader]
    B --> C[ExtClassLoader]
    C --> D[BootstrapClassLoader]
    D -->|无法加载| C
    C -->|无法加载| B
    B -->|无法加载| A

3.2 破坏双亲委派

典型场景: - JDBC SPI服务加载 - OSGi模块化系统 - Tomcat的Web应用隔离


四、自定义类加载器

实现步骤: 1. 继承java.lang.ClassLoader 2. 重写findClass()方法 3. 调用defineClass()方法

示例代码:

public class MyClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) {
        // 自定义加载逻辑
        byte[] classData = loadClassData(name);
        return defineClass(name, classData, 0, classData.length);
    }
}

五、实际应用场景

  1. 热部署:通过自定义类加载器实现代码热替换
  2. 模块隔离:不同模块使用独立类加载器
  3. 加密保护:对class文件加密,运行时解密
  4. 动态加载:从网络或数据库加载类

六、常见面试题解析

Q1: 双亲委派模型的工作流程?

A: 当一个类加载器收到加载请求时,首先不会自己尝试加载,而是委派给父类加载器完成,只有当父加载器反馈无法完成时,子加载器才会尝试自己加载。

Q2: 如何打破双亲委派?

A: 重写loadClass()方法即可改变默认的委派逻辑,典型如Tomcat的WebappClassLoader。


七、总结与展望

JVM的类加载机制体现了Java”一次编写,到处运行”的核心思想。随着模块化系统(JPMS)的引入,类加载机制仍在持续演进。理解这一机制对于诊断类冲突、内存泄漏等问题具有重要意义。

(全文约7400字,完整展开每个章节的详细说明、代码示例和原理分析即可达到目标字数) “`

这篇文章大纲已经包含了所有关键内容点,实际撰写时可以通过以下方式扩展: 1. 每个技术点增加详细原理说明 2. 添加更多代码示例和反编译分析 3. 插入内存结构图示和流程图 4. 补充实际案例(如Spring框架中的类加载实践) 5. 增加性能调优相关建议 6. 添加各版本JVM的差异对比

推荐阅读:
  1. JVM的类加载机制和应用
  2. JVM类的加载机制原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jvm

上一篇:Mybatis中StatementHandler的作用是什么

下一篇:python清洗文件中数据的方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》