上篇中我们讲解了Class文件,这篇我们说说虚拟机是如何加载这些Class文件的?Class文件中的信息进入到虚拟机后会发生什么变化?这就涉及到了类加载机制。
类加载机制是把类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的java类型。这一系列的过程都是在程序运行期间完成的。
类加载器
类加载器就是下图中红框的部分,它通过一个类的全限定名来获取描述此类的二进制字节流,从而将java类动态地加载进JVM的内存空间中。
适用情景
对于一个非数组类的加载阶段,可以使用系统提供的引导类加载器来完成,也可以由用户自定义的类加载器去完成。
对于数组类而言,其由java虚拟机直接创建,不通过类加载器。
双亲委派机制
双亲委派机制是类加载所采取的一种方式。如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。每一层的类加载器均是如此。只有当父加载器反馈自己无法完成这个请求时,子加载器才会尝试自己去加载。
类比到现实:小明想买一个玩具挖土机,可他又不好意思直接张口说。所以,发生了下面的对话。
小明去问他爸爸:爸爸你有挖土机吗?
爸爸说:没有哎
接着爸爸问爷爷:爸爸爸爸,你有挖土机吗?
爷爷说:没有哎
接着爷爷问太爷爷:爸爸爸爸,你有挖土机吗?
太爷爷说:我也没有。让重孙子去买一个吧。
结果小明就高高兴兴地自己去买了一个玩具挖土机。
分类
启动类加载器是使用C++实现的,是虚拟机自身的一部分。
其它类加载器是由java语言实现的,独立于虚拟机外部,并且全都继承自抽象类java.lang.ClassLoader。
好处
以String类为例。就算是用户自己写了一个String类的实现,那对此类进行加载时,也只会委派给启动类加载器来对JDK中原本的String类进行加载,而自定义的String类永远不会被调用。这样保证了系统的安全。
什么时候进行类加载?
有且只有以下5种方式必须立即对类进行加载
(1)使用new实例化对象的时候;读取或配置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候;调用一个类的静态方法的时候。
(2)使用java.lang.reflect包的方法对类进行反射调用的时候。如果类没有进行过初始化,则需要先触发其初始化。
(3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
(4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的类),虚拟机会先初始化这个主类
类加载过程详述
类加载过程分为5步。大部分都是由虚拟机主导和控制的,除了以下两种情形:
在加载阶段
开发人员可以通过自定义类加载器参与
在初始化阶段
会执行开发人员的代码去初始化类变量和其它资源
1、加载
虚拟机需要完成的事情:
(1) 通过一个类的全限定名来获取定义此类的二进制字节流。
(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
(3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
2、验证
验证的目的是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,不会危害虚拟机自身的安全。
其分为4个步骤:文件格式验证,元数据验证,字节码验证,符号引用验证。其中文件格式验证是直接对字节流进行操作的,其余3项是在方法区中进行的。
3、准备
此阶段是正式为类变量分配内存并设置类变量初始值的阶段。其是在方法区中进行分配的。有两个注意点:
(1)此时只是对类变量(被static修饰的变量)进行内存分配,而不是对象变量。给对象分配内存是在对象实例化时,随着对象一起分配到java堆中。
(2)如果一个类变量没有被final修饰,则其初始值是数据类型的零值。比如int类型的是0,boolean类型的是false。举个例子来说明:
public static int value=123;
在准备阶段过后的初始值为0而不是123,因为这个时候尚未开始执行任何java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器6bec87a23a27cb798bd98bfe687c7043()方法之中。所以把value赋值为123的动作将在初始化阶段才会执行。
public static final int value=123;
此时因为有final,所以在准备阶段value就已经被赋值为123了。
4、解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。可对类或接口、字段、类方法、接口方法等进行解析。
符号引用是什么:
符号引用就是包含类的信息,方法名,方法参数等信息的字符串,它供实际使用时在该类的方法表中找到对应的方法。
直接引用是什么:
直接引用就是偏移量,通过偏移量可以直接在该类的内存区域中找到方法字节码的起始位置。
符号引用是告诉你此方法的一些特征,你需要通过这些特征去寻找对应的方法。直接引用就是直接告诉你此方法在哪。
5、初始化
此阶段用于初始化类变量和其它资源,是执行类构造器6bec87a23a27cb798bd98bfe687c7043()方法的过程,此时才是真正开始执行类中定义的java程序代码。
以上是对JAVA虚拟机类加载机制的详细讲解,更多相关问题请访问PHP中文网:JAVA视频教程
以上是JAVA虚拟机(JVM)详细介绍(五)——类加载机制的详细内容。更多信息请关注PHP中文网其他相关文章!

本文讨论了使用Maven和Gradle进行Java项目管理,构建自动化和依赖性解决方案,以比较其方法和优化策略。

本文使用Maven和Gradle之类的工具讨论了具有适当的版本控制和依赖关系管理的自定义Java库(JAR文件)的创建和使用。

本文讨论了使用咖啡因和Guava缓存在Java中实施多层缓存以提高应用程序性能。它涵盖设置,集成和绩效优势,以及配置和驱逐政策管理最佳PRA

本文讨论了使用JPA进行对象相关映射,并具有高级功能,例如缓存和懒惰加载。它涵盖了设置,实体映射和优化性能的最佳实践,同时突出潜在的陷阱。[159个字符]

Java的类上载涉及使用带有引导,扩展程序和应用程序类负载器的分层系统加载,链接和初始化类。父代授权模型确保首先加载核心类别,从而影响自定义类LOA

本文解释了用于构建分布式应用程序的Java的远程方法调用(RMI)。 它详细介绍了接口定义,实现,注册表设置和客户端调用,以解决网络问题和安全性等挑战。

本文详细介绍了用于网络通信的Java的套接字API,涵盖了客户服务器设置,数据处理和关键考虑因素,例如资源管理,错误处理和安全性。 它还探索了性能优化技术,我

本文详细介绍了创建自定义Java网络协议。 它涵盖协议定义(数据结构,框架,错误处理,版本控制),实现(使用插座),数据序列化和最佳实践(效率,安全性,维护


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

Dreamweaver Mac版
视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能