什么是类的加载

将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

类的生命周期

类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,分别是加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(using)、和卸载(Unloading)七个阶段。其中验证、准备和解析三个部分统称为连接(Linking),

图解:

1.加载

查找并加载类的二进制数据,步骤如下:

  • 通过一个类的全限定名来获取其定义的二进制字节流。

  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

  • 在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。

2.连接

将Java类的二进制代码合并到JVM的运行状态中的过程

(1)验证:确保加载的类信息符合JVM规范,没有安全方面的问题

  • 文件格式的验证:是否以0xCAFEBABE开头、版本号是否合理

  • 元数据验证:是否有父类、继承了final类、非抽象类实现了所有的抽象方法

  • 字节码验证(复杂):运行检查、栈数据类型和操作码参数吻合、跳转指令到合理的位置

  • 符号引用验证:确保解析动作能正确执行。

(2)准备:为类变量(static变量)分配内存并保存设置类变量初始值的阶段,这些值都在方法区中进行分配。(int a = 3;准备阶段a=0,在初始化时才赋值3)对static final类型的数据,在准备阶段就会被赋值。

(3)解析:将虚拟机常量池内的符号引用替换为直接引用的过程

3.初始化

(1)初始化阶段是执行类构造器()方法的过程,该方法由编译器自动收集类中的所有类变量的赋值操作和静态语句块中的语句合并产生的。

(2)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需先发出父类的初始化

(3)虚拟机会保证一个类的< clinit>()方法在多线程环境中被正确加锁和同步。

4.类初始化时机

只有当对类的主动使用的时候才会导致类的初始化

(1) 类的主动引用(一定会发生类的初始化)

① New 一个类的对象

② 调用类的静态成员(除了final常量)和静态方法

③ 使用java.lang.reflect包的方法对类进行反射调用

④ 当虚拟机启动时,java Hello,则一定会初始化Hello类,即先启动main方法所在的类

⑤ 当初始化一个类,若父类没有初始化则先会初始化父类

(2) 类的被动引用

① 当访问一个静态域时,只有真正声明这个域的类才会被初始化(通过子类引用父类的静态变量,不会导致子类的初始化

② 通过数据定义类的引用(定义对象数组),不会触发此类的初始化,

③ 引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中了)

④通过类名获取Class对象,不会触发类的初始化,

⑤通过ClassLoader默认的loadClass方法,也不会触发初始化动作

5.结束生命周期

Java虚拟机将结束生命周期有以下几种情况

  • 执行了System.exit()方法

  • 程序正常执行结束

  • 程序在执行过程中遇到了异常或错误而异常终止

  • 由于操作系统出现错误而导致Java虚拟机进程终止

双亲委派模型

1.JVM预定义的三种类加载器

如图

注:这里父类加载器并不是通过继承关系来实现的,而是采用组合实现的

(1)启动(引导)类加载器(bootstrap class loader)

加载Java的核心库,是用原生代码(c/c++)实现的,加载扩展、应用程序类加载器,并指定它们的父类加载器 rt.jar 参数:-Xbootclasspath

(2)扩展类载器(Extension ClassLoader):

该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载DK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器

(3) 应用程序类加载器(Application ClassLoader)

该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

(4) 自定义类加载器:通过继承java.long.Classloader类,来实现自己的类加载器。

2.JVM类加载机制

(1)全盘负责

当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入

(2)父类委托

先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类

(3)缓存机制

缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效

3.类加载器的代理模式

(1) 定义:交给其他代理器来加载指定的类

(2) 双亲委托机制:

  • 某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,知道最高层,如果父类加载器可以完成类加载任务,就成功返回,只有父类加载器无法完成此加载任务时,自己才去加载。

  • 为了保证Java核心库的类型安全(保证不会出现用户自己定义java.long.Object类的情况

  • 也是安全的最基本屏障

(3) 双亲委托机制是代理模式的一种,并不是所有的类加载器都采用双亲委托机
制,

(4) Tomcat服务器加载器也使用代理模式,所不同的是它是首先去尝试加载某个类,如果找不到再代理给父类加载器,与一般类加载器的顺序相反

4.线程上下文加载器

  • 基本思想:在顶层ClassLoader中,传入底层ClassLoader的实例。

  • 通过Thread.setContextClassLoader()反复设置

  • 一个角色、解决顶层ClassLoader无法访问底层ClassLoader类的问题、

5.OSGI模型

  • OSGI(Open Service Gateway Initative):Java的动态模块系统

  • 核心:多个类加载器,谁的组件谁来加载

6.热替换

当一个class被替换后,系统无需重启,替换的类立即生效。

本人才疏学浅,若有错,请指出
谢谢

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览106372 人正在系统学习中

[转帖]【JVM】类加载机制的更多相关文章

  1. JVM基础系列第7讲:JVM 类加载机制

    当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...

  2. JVM总结(四):JVM类加载机制

    这一节我们来总结一下JVM类加载机制.具体目录如下: 类加载的过程 类加载过程概括 说说引用 详解类加载全过程: 加载 验证 准备 解析 初始化 虚拟机把描述类的数据从Class文件加载到内存,并对数 ...

  3. JVM 类加载机制详解

    如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lan ...

  4. Java虚拟机(四):JVM类加载机制

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

  5. JVM类加载机制详解(二)类加载器与双亲委派模型

    在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...

  6. JVM类加载机制(转)

    原文出自:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运 ...

  7. JVM类加载机制详解

    引言 如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 在加载阶段,虚拟机需要完成以下三件事情: 1)通过一个类的全限定名来获取定义此 ...

  8. Android动态加载--JVM 类加载机制

    动态加载,本质上是通过JVM类加载机制将插件模块加载到宿主apk中,并通过android的相关运行机制,实现插件apk的运行.因此熟悉JVM类加载的机制非常重要. 类加载机制:虚拟机把描述类的数据从C ...

  9. Java虚拟机(五):JVM 类加载机制

    一.JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 1. 加载: 加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表 ...

  10. 深入理解JVM虚拟机6:深入理解JVM类加载机制

    深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...

随机推荐

  1. 知识+AI融合创新探索,华为云论文被AI顶级学术期刊IEEE TPAMI接受

    摘要:通过利用物体类别之间存在的层级关系约束,自动学习从数据中抽取识别不同类别的规则,一方面对模型的预测过程进行解释,另一方面也提供了一条引入人工先验知识的可行途径. 前言 受益于深度学习技术的突破, ...

  2. 快来一起玩转LiteOS组件:Curl

    摘要:Curl是一个文件传输工具,常用于数据上传和下载,本demo基于Cloud_STM32F429IGTx_FIRE开发板演示了在curl demo中调用curl提供的API来下载一个文件,并将其保 ...

  3. 火山引擎 DataLeap:如何构建一套完整、易用的数据标准体系

    数据标准是数据治理体系中的核心要素之一.   一方面,统一的数据标准可以在复杂的业务场景下,帮助团队对齐数据口径,提升数据在分析.诊断等场景的质量与效率:另一方面,数仓团队与分析师团队也需要沉淀一套敏 ...

  4. Codeforces Round 913 (Div. 3)

    CF1907总结 A. Rook 题面翻译 给出车在国际象棋棋盘中的位置,输出其可到达的坐标(不必在意顺序). 车可以横着或竖着走任意格数. 分析 题意明了,输出车所在行和列所有格子的序号(除车所在位 ...

  5. Spring相关原理

    Spring是什么? Spring是一个轻量级的IoC和AOP容器框架.常见的配置方式有三种:基于XML的配置.基于注解的配置.基于Java的配置. 模块分为以下:Spring Core:Spring ...

  6. 【调试】ftrace(二)新增跟踪点

    内核的各个子系统已经有大量的跟踪点,如果这些跟踪点无法满足工作中的需求,可以自己手动添加跟踪点. 添加跟踪点有两种方式,一种是仿照events/目录下的跟踪点,使用TRACE_EVENT() 宏添加. ...

  7. UNI-APP 使用Echart

    UNI-APP 使用Echart(含地图教程) https://blog.csdn.net/weixin_43548442/article/details/121468189 uniapp使用echa ...

  8. lucene.net全文检索(二)lucene.net 的封装

    查询 public class LuceneQuery : ILuceneQuery { #region Identity private Logger logger = new Logger(typ ...

  9. 电脑面试两道问题(python+shell)

    最近面试电脑代码面试遇到两个问题,供大家参考一下一.python脚本: 手写一个函数,实现两个数相加,并使用unittest与pytest工具测试函数正确性. 1.unnitest进行测试: impo ...

  10. java进阶(7)--Object类-toString()/equals()/finalize()/hashCode()

    一.object类介绍 object类这个老祖宗中的方法,所有子类通用,直接或间接继承. 学习常用方法即可 列表 prtected object clone()             //对象克隆 ...