深入解析JVM加载机制

一、背景

Java代码被编译器变成生成Class字节码,但字节码仅是一个特殊的二进制文件,无法直接使用。因此,都需要放到JVM系统中执行,将Class字节码文件放入到JVM的过程,简称类加载

二、整体流程

在这里插入图片描述

三、阶段逻辑分析

3.1 加载Loading

3.1.1 字节码来源

由于类的Class二进制字节码来源可能不同,JVM在此处做了扩展,通过类的全限定名来加载不同来源的二进制字节码文件。以下是一些可能的来源:

  1. 本地文件中获取;
  2. 网络上获取;
  3. 压缩包中获取;
  4. 加密文件中获取;
  5. 运行时内存中获取。例如使用动态代理技术时,进行字节码重组,最终生成的二进制字节流就会在内存获取。

3.1.2 加载步骤

【步骤1】:通过类的全限定名获取类的二进制字节流;
【步骤2】:将二进制字节码中的静态存储结构转化为方法区的运行时数据结构,同时在方法区会生成InstanceKlass对象。下面详细讲解一下字节码文件:
字节码的组成
在这里插入图片描述

一般信息:
1. 魔数
2. 字节码文件对应的Java版本号
3. 访问标识(用于区分类、接口、枚举或注解等类型)
4. 子类、父类和接口的索引,用于找到子类、父类或结构的信息。索引指的在常量池中的位置

在这里插入图片描述

常量池:
1. 字符串常量
2. 类、接口名或字段名
其中的 #数字 即符号引用,表示在常量池中的位置。从图中可以看出,有String_info,Class_info,Methodref_info等信息,字符串常量池仅是其中的一小部分。

在这里插入图片描述

字段:当前类或接口声明的字段信息
方法:当前类或接口声明的方法信息
属性:类的属性

在这里插入图片描述
【步骤3】:在内存【堆中】中生成一个当前类的Class对象,作为访问方法区的入口
在这里插入图片描述

疑问:为什么有了InstanceKlass对象,还需要Class对象
1.InstanceKlass对象是C++语言生成的对象,因此Java代码无法直接操作InstanceKlass对象;
2.Klass对象中不仅包含类的基本信息,还包括虚方法表信息。虚方法表信息是给Java虚拟机使用的,开发者没有权限使用,因此创建一个简单的Class对象,给开发者使用,这样Java虚拟机就能很好的控制开发者访问数据的范围

3.2 链接Linking

3.2.1 验证

文件格式验证、元数据信息验证、字节码正确性验证以及符号引用存在性验证。

3.2.2 准备

  1. static final修饰的基本变量,进行显示初始化赋值。【隐士初始化在编译器阶段已经完成】
  2. static 修饰的变量,分配内存空间,并进行隐士初始化赋值。JDK7放在方法区中,JDK8放在堆中。

3.2.3 解析

编译阶段:由于尚未加载到内存,并不知道实际的内存引用关系,仅是通过特殊方式#数字将具有引用关系的属性记录下来,最终形成符号引用;
运行阶段:各种属性已经被分配过内存空间了,因此它们有实际的内存地址。此时根据符号引用,将属性之间的引用关系转化为内存地址的实际引用关系,最终变成直接引用。

3.3 初始化Init

主要是编译器自动收集类中所有的静态变量以及静态代码块赋值动作,生成<clinit>方法,按照代码赋予的值进行赋值。编译器收集的顺序主要是语句在代码中出现的顺序决定的。
触发类的初始化的几种方式:

1. 访问一个类的```静态变量或静态方法```,但若变量是final修饰且等号右边是常量的,不会触发初始化;
2. 调用Class.forName(String className)方法;
3. 通过new 创建对象;
4. 执行Main方法的当前类

无法触发类的初始化的几种方式:

1. 无静态代码块且无静态赋值语句;
2. 仅有静态变量的声明无赋值操作;
3. 静态变量的定义使用final修饰

父子类的初始化规则:

1. 直接访问父类的静态变量,不会触发子类的初始化;
2. Java虚拟机保证子类的<clinit>方法执行之前,父类的<clinit>一定已经执行完毕,所以父类中的静态变量和静态代码块是优先于子类的静态变量和静态代码块执行的;

3.4 使用和卸载

使用:表示当前类正在被使用
卸载:表示已经被垃圾回收

相关推荐

  1. JVM】类机制

    2024-03-13 10:28:01       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-13 10:28:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-13 10:28:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-13 10:28:01       87 阅读
  4. Python语言-面向对象

    2024-03-13 10:28:01       96 阅读

热门阅读

  1. leetcode 4405.统计子矩阵

    2024-03-13 10:28:01       42 阅读
  2. c# 数组的使用

    2024-03-13 10:28:01       37 阅读
  3. Linux 配置安装ftp 运维工程师必备技能难度***

    2024-03-13 10:28:01       49 阅读
  4. 第四章、计算机网络5分

    2024-03-13 10:28:01       35 阅读
  5. markdown(详细)快速入门

    2024-03-13 10:28:01       44 阅读
  6. go语言数组使用

    2024-03-13 10:28:01       43 阅读
  7. 计算机网络 TCP协议的流量控制

    2024-03-13 10:28:01       46 阅读
  8. 软考笔记--层次式架构之中间层架构设计

    2024-03-13 10:28:01       43 阅读
  9. 数据结构——KMP

    2024-03-13 10:28:01       46 阅读
  10. c# DbHelper的封装

    2024-03-13 10:28:01       38 阅读