码迷,mamicode.com
首页 > 其他好文 > 详细

虚拟机类加载机制

时间:2021-01-26 12:03:05      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:请求   完成   应该   系统变量   不能   虚拟机   包括   引用   extc   

1.类加载的过程

    在java语言里,类型的加载,链接和初始化过程都是在程序运行期间完成的。类被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(loading),验证(verification),准备(preparation),解析(resolution),初始化(initializtion),使用(using)和卸载(unloading)7个阶段。

  • 加载:加载阶段,虚拟机需要完成3件事情
  1. 通过一个类的全限定名来获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
  • 验证:验证是链接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。从整体上看,验证阶段大致上会完成下面4个阶段的验证动作:文件格式验证,元数据验证,字节码验证,符号引用验证。
  • 准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。
  • 解析:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
  • 初始化:初始化阶段是类加载过程的最后一步,根据程序员通过程序指定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。
  1. <clinit>()方法是由编译器自动收集类中的所有变量的赋值动作和静态语句块中的语句合并产生的,编译器收集的顺序是有语句在源文件中出现顺序所决定的。
  2. <clinit>()方法与类的构造函数不同,它不需要显示的调用父类的构造器,虚拟机会保证在子类的<clinit>()方法执行之前,弗雷的<clinit>()方法已执行完毕。因此在虚拟机中第一个被执行的<clinit>()方法的类肯定是java.lang.Object
  3. <clinit>()方法对于类或者接口来说并不是必需的,如果一个类中没有静态语句块,也没有对变量的赋值操作,那么编译器可以不为这个类生成<clinit>()方法
  4. 接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因此接口与类一样都会生成<clinit>()方法。但是接口与类不同,执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法,另外,接口的实现类在初始化时也一样不会执行接口的<clinit>()方法
  5. 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁,同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法

2.类加载器

    虚拟机设计团队把类加载阶段中的"通过一个类的全限定名来获取描述此类的二进制字节流"这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类,实现这个动作的代码模块称为"类加载器“

  1. 启动类加载器(Bootstrap ClassLoader):这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootcclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被java程序直接引用。
  2. 扩展类加载器(Extensiion ClassLoader):这个加载器有sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中所有的类库,开发者可以直接使用扩展类加载器
  3. 应用程序类加载器(Application ClassLoader):这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(ClassPaht)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器

    双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载

虚拟机类加载机制

标签:请求   完成   应该   系统变量   不能   虚拟机   包括   引用   extc   

原文地址:https://www.cnblogs.com/bamboocool/p/14321501.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!