[转帖]【JVM】类加载机制
什么是类的加载
将类的.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被替换后,系统无需重启,替换的类立即生效。
本人才疏学浅,若有错,请指出
谢谢
[转帖]【JVM】类加载机制的更多相关文章
- JVM基础系列第7讲:JVM 类加载机制
当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...
- JVM总结(四):JVM类加载机制
这一节我们来总结一下JVM类加载机制.具体目录如下: 类加载的过程 类加载过程概括 说说引用 详解类加载全过程: 加载 验证 准备 解析 初始化 虚拟机把描述类的数据从Class文件加载到内存,并对数 ...
- JVM 类加载机制详解
如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lan ...
- Java虚拟机(四):JVM类加载机制
1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...
- JVM类加载机制详解(二)类加载器与双亲委派模型
在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...
- JVM类加载机制(转)
原文出自:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运 ...
- JVM类加载机制详解
引言 如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 在加载阶段,虚拟机需要完成以下三件事情: 1)通过一个类的全限定名来获取定义此 ...
- Android动态加载--JVM 类加载机制
动态加载,本质上是通过JVM类加载机制将插件模块加载到宿主apk中,并通过android的相关运行机制,实现插件apk的运行.因此熟悉JVM类加载的机制非常重要. 类加载机制:虚拟机把描述类的数据从C ...
- Java虚拟机(五):JVM 类加载机制
一.JVM 类加载机制 JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 1. 加载: 加载是类加载过程中的第一个阶段,这个阶段会在内存中生成一个代表 ...
- 深入理解JVM虚拟机6:深入理解JVM类加载机制
深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...
随机推荐
- MySQL篇:第六章_详解mysql视图
周末有朋友来上海没来得及更新,特此更两篇以正身 视图 含义:理解成一张虚拟的表 视图和表的区别: 使用方式 占用物理空间 视图 完全相同 不占用,仅仅保存的是sql逻辑 表 完全相同 占用 视图的好处 ...
- makefile:带你了解一种常用于GNU gcc编译的工具语言
摘要:该文章主要介绍makefile,一种常用语GNU gcc编译的工具语言,同时LiteOS也是利用该文件对工程项目进行make构建生成执行文件的. LiteOS源码中使用makefile进行文件的 ...
- 万字长文|大数据学前准备之Linux入门笔记(附资料)
对于大数据学习而言,Linux运维可以说是必备的技能.可以不研究的过于高深,但是基本的操作和使用一定要熟练.Linux的学习需要大量的实践,本文从linux的基本知识,实战操作,到常用的指令与软件安装 ...
- SyntaxError: Non-ASCII character #-*- coding:utf-8 -*-
执行python报错 /usr/bin/python2.7 /root/demo.py File "/root/demo.py", line 2 SyntaxError: Non- ...
- Sublime Text 16进制显示
大文件推荐使用 UltraEdit 工具 Sublime Text 16进制显示(可以直接显示不同数据类型转换后的结果,不用在线工具,转二进制了) 安装 HexViewer 插件 1. Ctrl + ...
- SpringBoot 拦截器 统一日志 记录用户请求返回日志
你请求我接口,传了什么参数,我返回了什么值给你,全部记下来.防止扯皮 需求:记录每次用户请求Controller的Body参数, 思路:在每个Controller 该当中记录,容易漏记,如果在拦截器里 ...
- 我“采访”了 ChatGPT
我"采访"了 ChatGPT 大家好,我是准备认真码字的**老章:. 最近ChatGPT火的爆表,看了很多相关文章,特别焦虑,唯恐自己的进步赶不上 AI 的发展. 还有就是我非常看 ...
- 文件描述符&文件句柄
一.概念 1.1 文件描述符&文件描述符表 文件描述符(file descriptor, fd)是Linux系统中对已打开文件的一个抽象标记,所有I/O系统调用对已打开文件的操作都要用到它.这 ...
- Windows Tools | How To Install VS Microsoft C++ Build Tools on Windows
This can be used for installing anything that requires C++ compiler on Windows. Installation steps D ...
- Spring 学习笔记(4)依赖注入 DI
本篇文章主要对 Spring 框架中的核心功能之一依赖注入 (DI,Dependency Injection) 进行介绍,也是采用 理论+实战 的方式给大家阐述其中的原理以及明确需要注意的地方. 相关 ...