总结篇(15)---JVM(java虚拟机) (2)类加载器

本文详细介绍了Java中的类加载过程,包括加载、验证、准备、解析和初始化五个阶段,并阐述了类加载器的不同类型及其工作原理,同时解释了双亲委派模型的作用。

类加载器

  • 类加载器是用来完成类的加载的。

一、JVM中类加载器相关的基本概念


  • (1)类的加载和卸载

        JVM将指定的class文件读取到内存里,并运行该class文件里的java程序的过程,就称之为“类的加载”;
        反之,将某个class文件的运行时数据从JVM中移除的过程,就称之为“类的卸载”。
    

  • (2)类的生命周期

        Java类从被虚拟机加载开始,到卸载出内存为止,它的生命周期包括:
            加载(Loading)、
            验证(Verification)、
            准备(Preparation)、
            解析(Resolution)、
            初始化(Initialization)、
            使用(Using)、
            卸载(Unloading)
        7个阶段。
        其中验证、准备、解析又称为连接(Linking)阶段。

二、类加载过程


  • 类加载过程:Class文件被JVM加载至JVM内存,在内存中验证、准备、解析、初始化之后,形成可以被JVM直接使用的java类型。

类加载过程是在Java程序运行期间完成,虽然会损耗一部分性能,但提高了Java语言的灵活性,体现在动态扩展方面,例如:多态(晚期绑定)。

类加载主要有以下几个步骤:
1、加载:在加载阶段,虚拟机主要完成以下三件事情:

        1)通过class文件的路径读取到二进制流。
        2)解析二进制流将里面的元数据(类型、常量等)载入到方法区。
        3)在java堆中生成对应的java.lang.Class对象。


2、连接

        连接过程又分为3步,验证、准备、解析
        
2.1、验证:判断class文件的合法性


2.2、准备:分配内存,给类的一些字段设置初始值。

        比如:
        public static int a = 1;在准备阶段a的值会初始化为0,到后面的初始化时才会设置为1.
        public final static int b = 1;在准备阶段就会被设置成指定的值,即b在准备阶段设为1。

2.3、解析:将符号引用替换成直接引用。

        比如:某个类继承Object,原来的符号引用记录的是“java.lang.object”这个符号,但不能找到该对象在哪。
        直接引用就是要找到“java.lang.object”所在的内存地址,建立直接引用关系,这样就方便查询到具体对象。
        
3、初始化:主要包括执行类构造方法、static变量赋值语句、static{}语句块

        需要注意的是:
            一个类进行初始化,那么会先初始化其父类,保证父类在子类之前被初始化。
            所以在java中初始化一个类,必先初始化java.lang.object,因为所有的java类都继承java.lang.object。


三、类加载器以及双亲委派模式


类加载器有一下几个:

1. 引导类加载器(Bootstrap ClassLoader):在jvm运行时,内嵌在jvm中的一段特殊的用来加载java核心类库的C++代码。
2. 扩展类加载器(Extension ClassLoader):用来加载jvm实现的一个扩展目录,该目录下的所有java类都由此类加载器加载。
3. 应用类加载器(Application ClassLoader):又称系统类加载器,主要负责加载程序开发者自己编写的java类。
4. 自定义加载器(Custom ClassLoader):通过java.lang.ClassLoader的子类自定义加载class。

在选用类加载器的时候,先会自下向上检查类是否被加载,
那么从Application ClassLoader 到 Bootstrap ClassLoader 检查是否被加载了(通过findLoaderClass),如果没有加载,则会交给父类,直到没有父类。
如果仍然没有,自顶向下尝试加载类,
那么从Bootstrap ClassLoader 到 App ClassLoader依次尝试加载。

双亲委派模型:

        如果一个类加载器收到了某个类的请求,则该类加载器并不会加载该类,而是把这个请求委派给父类加载器,每一个层次类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的启动类加载器;
        只有当父类加载器,在其搜索范围内无法找到所需的类,并将该结果反馈给子类加载器,子类加载器会尝试去加载。
        这就是双亲委派模型。

备注:

1)不同的类加载器加载同一类,加载后的对象是完全不一样的。

        即使两个类来源于相同的class文件,如果使用不同的类加载器,加载后的对象是完全不同的。
        这个不同反应在对象的equals()、isAssignableFrom()、isInstance()等方法的返回结果,包括了使用isntanceof关键字对对象所属关系的判定结果。

2)为什么使用双亲委派?

        一个是安全性,另一个就是性能;(避免重复加载 和 避免核心类被篡改)
        

 个人觉得不是重点,但提一下。
        例子:Tomcat的WebappClassLoader 就会先加载自己的Class,找不到再委托parent;
        

        双亲模式是默认的模式,但不是必须这么做;
        由于用户对程序动态性的追求导致的,这里所说的“动态性”指的是当前一些非常“热门”的名词:代码热替换、模块热部署等,简答的说就是机器不用重启,只要部署上就能用。
        
        举例:
        OSGi实现模块化热部署的关键则是它自定义的类加载器机制的实现。每一个程序模块(Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换。

4)什么场景下需要一个自定义的类加载器吗

使用场景:

        1)热部署:为了能够在不停止应用的情况下更新代码,可以使用自定义类加载器来实现热部署功能。

        2)隔离性:当你需要在同一JVM中运行多个应用程序并且希望它们彼此之间相互隔离(例如不同的Web应用程序),可以通过为每个应用程序创建独立的类加载器来实现。

        3)从非标准源加载类:如果你的应用程序需要从数据库、网络或者其他非文件系统的存储介质加载类,则需要编写特定的类加载器来支持这种需求。

        4)加密类文件:如果出于安全考虑需要对类文件进行加密,那么你可以编写一个自定义类加载器来解密这些类文件并在运行时加载它们。

更多java基础总结(适合于java基础学习、java面试常规题):

总结篇(1)---复用类

总结篇(2)---多态

总结篇(3)---内部类 (1)内部类的基本概念

总结篇(4)---内部类 (2)内部类之静态内部类

总结篇(5)---内部类 (3)内部类之成员内部类

总结篇(6)---内部类 (4)内部类之局部内部类

总结篇(7)---内部类 (5)内部类之匿名内部类

总结篇(8)---序列化

总结篇(9)---字符串及基本类 (1)字符串及基本类之基本数据类型

总结篇(10)---字符串及基本类 (2)字符串及基本类之java中公共方法及操作

总结篇(11)---字符串及基本类 (3)String对象

总结篇(12)---字符串及基本类 (4)Integer对象

总结篇(13)--- Java注解及元注解

总结篇(14)---JVM(java虚拟机) (1)JVM虚拟机概括

总结篇(15)---JVM(java虚拟机) (2)类加载器

总结篇(16)---JVM(java虚拟机) (3)运行时数据区

总结篇(17)---JVM(java虚拟机) (4)垃圾回收

总结篇(18)---JVM(java虚拟机) (5)垃圾回收算法

总结篇(19)---JVM(java虚拟机) (6)JVM调优

总结篇(20)---反射

总结篇(21)---Java IO

总结篇(22)---Java 进程

总结篇(23)---Java线程及其相关(1)线程介绍

总结篇(24)---Java线程及其相关(2)多线程及其问题

总结篇(25)---Java线程及其相关(3)线程池及其问题

总结篇(26)---Java线程及其相关(4)ThreadLocal

总结篇(27)---Java并发及锁(1)Synchronized

总结篇(28)---Java并发及锁(2)Volatile

总结篇(29)---Java并发及锁(3)Lock

总结篇(30)---Java并发及锁(4)常见锁及分类

总结篇(31)---JUC工具类(1)CountDownLatch

总结篇(32)---JUC工具类(2)CyclicBarrier

总结篇(33)---JUC工具类(3)Semaphore

总结篇(34)---JUC工具类(4)Exchanger

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sun cat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值