深入理解java虚拟机---4虚拟机类加载机制
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片、视频等原文的内容)
若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cnblogs.com/wengshuhang/p/10230798.html
类加载的整个生命周期:
加载、连接(验证、准备、解析)、初始化、使用、卸载。
加载:
class文件中的二进制数据读取到内存中,然后将该字节流所代表的静态数据结构转化为方法区中运行的数据结构,并且在堆内存中生成一个java.lang.Class对象作为访问方法区数据结构的入口
验证:
确保当前class文件的字节流所包含的内容符合当前JVM的规范要求,并且不会出现危害JVM自身安全的代码,当前字节流不符合规范会抛出VerifyError的异常,或者子异常,验证的信息有:
(1)文件格式:验证二进制文件是什么类型,验证是否符合当前JVM规范。
(2)元数据验证:检查类是否有父类、接口,验证其父类、接口的合法性, 验证被final修饰的类, 验证是否是抽象类,是否实现了父类的抽象方法或者接口中的方法, 验证方法的重载。
(3)字节码验证,主要验证程序的控制流程比如循环、分支等。
(4)符号验证,主要验证符号引用转换为直接引用时的合法性。
准备:
当一个Class文件的字节流通过验证,就开始为该对象的类变量,也就是静态变量,分配内存和初始值,各种数据类型的初始值基本都是0值,被final修饰则为指定值。
解析:
所谓解析就是指在常量池中找到类、接口、方法、字段的符号引用,并将其替换为直接引用的过程。
初始化:
执行<clinit>()方法(clinit是class initialize的简写),<clinit>()方法再编译过程中生成,此方法中包含了所有类变量的赋值以及静态代码语句块的执行代码,编译器收集的顺序是由执行语句在源文件中的出现顺序来决定的,静态语句块只能对后面的静态变量进行赋值,而不能对其进行访问
使用、卸载:
顾名思义,就是使用跟卸载。
双亲委派机制:
两种类加载器:
1、 启动类加载器(由C++实现,是虚拟机自身的一部分)(lib目录下的)
2、其他类加载器(由java语言实现,独立于虚拟机外,并且全部继承抽象类ClassLoader),包括:扩展类加载器(lib/ext目录下的)、应用程序类加载器(classPath上的类库)、自定义加载器。
除了顶层的启动类加载器,其他类加载器都必须要有自己的父类加载器,这种是以组合方式来复用父加载器的代码。
工作过程:类加载——>尝试父类加载parent.loadClass——>成功则加载完成,失败则自己加载findClass