JVM笔记 -- 来,教你类加载子系统
类加载子系统
类文件首先需要经过类加载子系统,进行加载,进类信息等加载到运行时数据区,生成Klass的实例。
在类加载子系统中有以下3个阶段操作(广义上的加载):
- 加载阶段
- Bootstrap ClassLoader:引导类加载器,主要加载JDK里面的核心类
- Extension ClassLoader:拓展类加载器
- Application ClassLoader:应用加载器
- 链接阶段
- 验证
- 链接
- 解析
- 初始化阶段
如果加载的时候失败了,则不会执行后面的链接等操作。
类加载子系统的作用:
- 类加载器子系统可以从本地文件或者网络中加载Class文件,Class文件开头有特定标识“CAFEBABY”(魔数)。
- 类加载器只负责将文件加载到运行时数据区,但是否可以运行,是执行引擎管的。
- 加载的类信息存放在方法区中,除了类信息以外,方法区还存放了运行时产量池信息,可能HIA包括字符串字面量和数字常量(这部分常量是Class文件中常量池部分的内存映射)。
譬如反编译后,会产生常量信息,里面包括常量以及符号引用等:
类加载器ClassLoader的角色,以下面的People.class为例:
通过类信息实例,可以通过new 实例化对象,也可以通过getClassLoader()获取类加载器,也可以通过实例getClass()获取类信息实例。
- People.class 存在本地硬盘上,相当于一个模板,最终可以实例化出n个同一个类但是属性不同的实例。
- People.class加载到JVM中,被称为DNA元数据模板,存放在方法区,也就是类信息。类信息也是对象。
- 从.class文件,到加载到JVM中,称为元数据模板,这个过程需要一个转换工具,这个工具就是类加载器(Class Loader)。
加载(Loading)
此处的加载,指的是类加载过程中的第一个阶段(环节),主要工作包括:
- 1.通过类的全限定名获取定义此类的二进制字节流。
- 2.将这个二进制字节流所代表的静态存储结构转化为方法区(JDK7以及之前叫永久代,JDK8之后成为元空间)的运行时数据结构。
- 3.在内存中生成一个该类的
java.lang.Class
对象,作为方法区该类的各种数据的访问入口,也就是类信息对象。
类的.class文件来源方式包括以下:
- 本地系统直接加载
- 网络传输获取
- 从zip压缩包读取
- 运行的时候计算生成,譬如动态代理技术
- 由其他文件生成,譬如场景:JSP
- 从加密文件中解密获得
链接
链接阶段又分为3个阶段:
- 验证:
- 目的是校验安全和法,确保Class文件的字节流中包含信息符合当前虚拟机要求,保证加载的类的正确性,不会危害到虚拟机的安全。
- 主要包括4种验证:
- 文件格式验证(譬如文件开头是"CAFEBABY")
- 元数据验证
- 字节码验证
- 符号引用验证
- 准备:
- 为类变量(static)分配内存并且设置该变量的默认初始值,即零值
- 不包含final修饰的static,因为final在编译的时候已经分配了,准备阶段会显示初始化。
- 不会为实例变量分配初始化,类变量会分配在方法区,但是实例变量是跟随对象一起分配在Java堆里面(一般情况)
- 解析:
- 将常量池的符号引用转化成为直接引用的过程
- 事实上,解析操作往往会伴随JVM在执行完初始化之后再执行
- 符号引用就是一组符号来描述所引用的目标,《Java虚拟机规范》的Class文件格式中,直接引用就是直接指向目标的指针,相对偏移量或者一个间接定位到目标的句柄。
- 解析这个阶段,主要是针对类或者接口,字段,类方法,接口方法,方法类型等等,对应的常量池中的CONSTANT_Class_info,CONSTANT_Fieldred_info,CONSTANT_Methodref_info等。
初始化
初始化,就是执行类的构造器<clinit>()
的过程,注意<clinit>()
是类的构造器,不是对象的。<clinit>()
是初始化类的,就是把类装到JVM里的初始化,不是运行时对象的初始化。
<clinit>()
这个方法不需要显式定义,而是javac
编译器自动收集类中的所有变量的赋值动作,加上静态代码块,合并成的一个方法。
<clinit>()
中代码的顺序和我们在类文件写的顺序一致。
执行子类的<clinit>()
方法之前,JVM会保证先执行其父类的<clinit>()
,默认父类是Object
。
仔细观察上面的代码,会发现,final的属性,即使是static修饰的,在<clinit>()
里面都不会存在,这是为什么呢?
这是因为final修饰的是常量,常量不会在初始化的时候执行赋值!!!常量在编译的时候已经分配了,准备阶段会显示初始化。
如果我们将final去掉,就可以发现,去掉final修饰,字节码就会加上该字段的赋值:(下面的ldc是指常量池的意思,从常量池编号为#6的地方,加载该常量)
虚拟机在初始化的时候,已经保证了类的<clinit>()
方法,即使在多线程的环境下,也只会执行一次,其底层的逻辑就是默认同步加锁了。
【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人写作方向:Java源码解析,JDBC,Mybatis,Spring,redis,分布式,剑指Offer,LeetCode等,认真写好每一篇文章,不喜欢标题党,不喜欢花里胡哨,大多写系列文章,不能保证我写的都完全正确,但是我保证所写的均经过实践或者查找资料。遗漏或者错误之处,还望指正。
平日时间宝贵,只能使用晚上以及周末时间学习写作,关注我,我们一起成长吧~
JVM笔记 -- 来,教你类加载子系统的更多相关文章
- JVM解毒——类加载子系统
带着问题,尤其是面试问题的学习才是最高效的.加油,奥利给! 点赞+收藏 就学会系列,文章收录在 GitHub JavaEgg ,N线互联网开发必备技能兵器谱 直击面试 看你简历写得熟悉JVM,那你说说 ...
- 【JVM之内存与垃圾回收篇】类加载子系统
类加载子系统 概述 完整图如下: 如果自己想手写一个 Java 虚拟机的话,主要考虑哪些结构呢? 类加载器 执行引擎 类加载器子系统作用 类加载器子系统负责从文件系统或者网络中加载 Class 文件, ...
- JVM上篇:类加载子系统
JVM类加载 目录 JVM类加载 1.内存结构概述 2.类加载子系统概述 3.类的加载过程 2.1加载 2.2Linking 2.2.1验证(Verify) 2.2.2准备(Prepare) 2.2. ...
- JVM笔记--如果你写JVM,最需要考虑的重要结构是什么?
开局一张图,前面已经从每一部分解析过JVM的内存结构了,现在按照顺序来分析: 整体上来看:类文件从类加载子系统,加载完成之后,主要存放在方法区(JRockit和H9没有方法区,这里指的是HotSpot ...
- JVM_02 类加载子系统
JVM细节版架构图 本文针对Class Loader SubSystem这一块展开讲解类加载子系统的工作流程 类加载子系统作用 1.类加载子系统负责从文件系统或者网络中加载class文件,class文 ...
- JVM笔记五-堆区
JVM笔记五-堆区 在JVM中,堆区是重中之重.通过前面文章的学习,我们知道了,栈区是不会有垃圾回收的,所以,经常说的垃圾回收,其实就是回收的是堆区的数据.在这里,我们将会看到传说中的,新生代.老年代 ...
- JVM2 类加载子系统
目录 类加载子系统 类加载器子系统 类加载器ClassLoader角色 类加载的过程 案例 加载Loading 连接Linking 初始化Intialization clinit() 类的加载器 虚拟 ...
- JVM专题1: 类和类加载机制
合集目录 JVM专题1: 类和类加载机制 Java对象的结构 在HotSpot虚拟机中, 对象在内存中存储的布局可以分为3块区域 对象头Header 实例数据Instance Data 对齐填充Pad ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
随机推荐
- js optional chaining operator
js optional chaining operator js 可选链 可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效. ?. 操作符的功能类似于 ...
- TypeScript Generics All In one
TypeScript Generics All In one TypeScript 泛型 代码逻辑复用 扩展性 设计模式 方法覆写, 直接覆盖 方法重载,参数个数或参数类型不同 test " ...
- 浏览器缓存 All In One
浏览器缓存 All In One HTTP 缓存 强缓存 expired Cache-Control max-age s-maxage 协商缓存 E-tag last-modified 本地缓存 co ...
- i18n 和 L10n (internationalization and localization) 国际化与本地化(具有全球战略眼光的公司企业的必由之路)
i18n 和 L10n (internationalization and localization) 国际化与本地化(具有全球战略眼光的公司企业的必由之路) 1 1 https://zh.wiki ...
- Android Jetpack All In One
Android Jetpack All In One 在2018年,我们推出了Android Jetpack作为一组库,以帮助开发人员遵循最佳实践,减少样板代码以及编写可在Android版本和设备之间 ...
- Kotlin 入门教程
Kotlin 入门教程 Android / Java https://developer.android.com/kotlin?hl=zh-cn 使用 Kotlin 开发 Android 应用 使用 ...
- Docker In Action
Docker In Action Docker 实战 https://docs.docker.com/get-started/overview/ Docker Engine Docker Archit ...
- Cocos Creator 游戏开发
Cocos Creator 游戏开发 https://www.cocos.com/products#CocosCreator 一体化编辑器: 包含了一体化.可扩展的编辑器,简化了资源管理.游戏调试和预 ...
- Python爬虫_百度贴吧(title、url、image_url)
本爬虫以百度贴吧为例,爬取某个贴吧的[所有发言]以及对应发言详情中的[图片链接] 涉及: request 发送请求获取响应 html 取消注释 通过xpath提取数据 数据保存 思路: 由于各贴吧发言 ...
- JVM系列(四):java方法的查找过程实现
经过前面几章的简单介绍,我们已经大致了解了jvm的启动框架和执行流程了.不过,这些都是些无关痛痒的问题,几行文字描述一下即可. 所以,今天我们从另一个角度来讲解jvm的一些东西,以便可以更多一点认知. ...