深入理解JVM(3) 虚拟机类加载模式

类加载的生命周期

在这里插入图片描述
有且只有以下需要立即初始化的情况:

  • 用new实例化对象时、读取或设置一个直接定义(非继承)的类型的静态非常量字段时、调用类的直接定义(非继承)的一个静态方法时
  • 使用java.lang.reflect包的方法对类型进行反射调用的时候,如果类型没有进行过初始化,则需要先触发其初始化(-XX:+TraceClassLoading参数也会导致子类加载)
  • 初始化子类时要先初始化父类
  • 先初始化带main的主类
  • 当使用JDK 7新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解
    析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄,并且这个方法句柄对应的类没有进行过初始化,则需要先触发其初始化。
  • 当一个接口中定义了JDK 8新加入的默认方法(被default关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,那该接口要在其之前被初始化

类加载的过程

加载

JVM做三件事

  1. 通过类全名获取其二进制字节流
  2. 将字节流转化为runtime数据结构
  3. 在内存中生成Class对象,作为方法区这个类的各种数据的访问入口

获取二进制字节流的方法不固定,这带来了许多应用,动态代理技术就应用于此

  • 非数组类型的加载阶段是开发人员可控性最强的阶段,可以自定义ClassLoader,重写一个类加载器的findClass()或loadClass()方法。
  • 数组不通过ClassLoader加载,但其元素类型要靠ClassLoader加载,其创建遵循以下规则:
    • 如果数组组件类型为引用类型(不是基本数据类型),递归采用上述加载过程,数组将被标识在加载该组件类型的类加载器的类名称空间上??
    • 如果是基础数据类型,Java虚拟机将会把数组标记为与引导类加载器关联

加载与连接阶段的部分动作是交叉进行的

验证

准备

解析

JVM将常量池内的符号引用替换为直接引用的过程

初始化

类加载器

类加载器基础

对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,每
一个类加载器,都拥有一个独立的类名称空间。所以说,类加载器也参与了类比较。

双亲委派模型

JVM的角度只有2种不同的类加载器:Bootstrap ClassLoader(C++实现,虚拟机一部分)和其他ClassLoader。
Java8及以前的程序使用非自定义加载类可分3种:

  • 启动类加载器(Bootstrap ClassLoader),其负责加载<JAVA_HOME>\lib目录,或者被-Xbootclasspath参数所指定的路径中存放的,而且是Java虚拟机能够识别的类文件到虚拟机内存。它无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器去处理,直接使用null代替即可
  • 扩展类加载器(Extension Class Loader),负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中所有的类库,这些类可以扩展JavaSE的功能。
  • 应用程序加载器,是ClassLoader.getClassLoader()的返回值,也被称为系统类加载器,负责加载用户classpath下的类,一般是默认的类加载器

在这里插入图片描述
上图中,各种类加载器之间的层次关系被称为类加载器的“双亲委派模型(Parents Delegation Model)”。它要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。这里类加载器使用组合关系而非继承关系来复用父加载器的代码。

双亲委派模型的工作流程

对每一个层次的加载器,当其收到类加载的请求,它首先委派给父加载器完成,而不是自己去执行。只有当父加载器反馈自己无法完成加载,子加载器才会尝试自己加载。

这样的模型:

  • 能够保重Java的类有了固定的层次关系,无论被哪个ClassLoader加载,都能保证使用顶层加载器,保证是同一个类。

代码逻辑指出:先检查请求加载的类型是否已经被加载过,若没有则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。假如父类加载器加载失败,抛出ClassNotFoundException异常的话,才调用自己的findClass()方法尝试进行加载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值