第七章:虚拟机类加载机制

本文介绍Java虚拟机的类加载过程,包括加载、验证、准备、解析和初始化等步骤。同时探讨了类加载器的种类及双亲委派模型的工作原理,并讨论了该模型可能被破坏的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一部分

概述:Class文件中描述的各种信息都需要加载到虚拟机中才能运行和使用。

                但是具体如何加载到虚拟机中?

                Class文件加载到虚拟机中之后会发生什么事情?

          虚拟机class文件加载到内存中,并且对class文件中的数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用        的java类型,这就是虚拟机的类加载机制。

类加载的时机:

        类的整个声明周期从加载到内存——>卸载出内存为止,共经历:加载,验证,准备,解析,初始化,使用,卸载。

                  其中:验证,准备,解析统称为连接。

                  其中:加载,验证,准备,初始化,卸载顺序是固定的。

       没有规定类加载的约束,但是有5种情况必须进行初始化。

                 1.使用new,getstatic,putstatic等关键字的时候。最常见的是实例化一个对象,读取或者设置一个类静态方法的时候,                   以及调用一个类静态方法的时候。

                 2.使用反射的时候,类还没有初始化。

                 3.当初始化子类的时候,其父类还没有被初始化。

                 4.启动虚拟机的时候,用户需要指定一个主类,虚拟机会先初始化这个类。

                 5.JDK1.7中,句柄所对应的类没有进行过初始化,则需要先出发其初始化。

  类加载的过程:

           加载:加载和类加载是两个概念。

                   1.通过一个类的全限定名来获取定义此类的二进制字节流。

                   2.将这个类静存储结构,转变为方法区运行时数据结构。

                   3.在内存中生成这个类的java.lang.class对象,作为在方法去访问这个类的各种数据的接口。

          验证:保证class文件的字节楼中包含的信息满足虚拟机要求,不会危害虚拟机。

                   1.文件格式验证,这个阶段是基于二进制字节流进行的,通过这个阶段之后字节流才能进入内存中的方法区进行存储。

                   2.元数据验证,针对的是字节码,验证是否满足java语言规范。

                   3.字节码验证,保证类的方法是合法的,符合逻辑的,在运行的时候是不会危害到虚拟机安全的。

                   4.符号引用验证,最后一个验证阶段发生在解析阶段中,是将符号转化为直接应用的时候。符号应用是可以看作是对类自身以                            的信息进行匹配检索 。

            准备:准备阶段是正式为类变量分配内存并设置初始值的阶段,这些变量所使用的内存都将是在方法区中进行的。这里分配的变                          量仅仅包括类变量,被static修饰的部分。

            解析:解析阶段是虚拟机将常量池中的符号引用转换为直接引用的过程。

第二部分

    类加载器:通过全限定名来获取描述此类的二进制字节流的过程中,用到的代码块称之为“类加载器”。

    双亲委派模型:

                     从Java虚拟机的角度来讲,类加载器分为启动加载器和其他的类加载器。启动加载器是虚拟机自身的一部分,由C++实现。                   其他类  加载器由java实现,独立于虚拟机外部。

                     从java开发人员的角度分为三种加载器:

                    启动加载器,扩展类加载器,应用程式类加载器:一般是默认的类加载器。

 类加载器之间的层次关系:其中除了启动类加载器外,其他的类加载器都有自己的父类加载器,而其是通过组合来实现复用代码的。

               启动类加载器

               扩展类加载器

               应用程序加载器

              自定义加载器

工作过程:先检测是否加载,如果没有加载则父类加载器加载,如果父加载器为空则默认使用启动类加载器,如果父加载器失败,就抛出异常,然后调用自己的findClass()方法进行加载。

 

破坏双亲委派模型:

 第一次被破坏:在双亲模型之前,人们集成java.lang.classloader唯一目的就是区复习loadclass(),因为虚拟机在加载loadclassinternal()方法的时候,唯一的逻辑就是区调用loadclass()。而现在已经不提倡覆盖loadclass了,而应该把类加载逻辑写到findclass()中,因为在loadclass()逻辑里面,如果父类加载失败就会调用findclass().

第二次破坏:双清委派模型在很好的解决了基础类的统一问题,越是基础的类由越网上的类加载器加载,而基础类之所以被称之为基础类就是因为他是被用户经常调用的api。但是有一个问题是当基础类要调用用户的类该怎么办。因此提出了线程上下文类加载器,也就是父加载器请求子类加载器去完成类加载的动作,这个双亲加载是相违背的。

第三次破坏:第三次破坏是由于人们追求程序动态性而导致的,比如,模块热部署,代码热替换。新提出的OSGi用于模块热部署则是其自定义的类加载器机制的实现。每一个程序模块中都有一个类加载器,当需要更新的时候,就将程序模块和其类加载器一起换掉。

 

              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值