JVM复习——类加载

1.类加载过程

加载、连接(验证、准备、解析)、初始化、使用、卸载。

加载、验证、准备、初始化、卸载顺序固定,解析可发生于初始化之前或之后。

加载:

  1. 通过类的全限定名找到对应的字节码文件并以二进制流读取;
  2. 根据字节码文件内容定义的静态存储结构在方法区(1.7永久代,1.8及以后元空间)生成对应的运行时数据结构;
  3. 在内存(1.6在方法区,1.7及以后在堆)中生成对应的Class对象,作为类方法的访问入口。

验证:

  1. 文件格式验证:
  2. 元数据验证:验证父类、继承、接口等java语法合法性
  3. 字节码验证:通过控制流及数据流验证程序的语义合法性,且是否会危害JVM
  4. 符号引用验证:符号引用解析为直接引用(发生于解析阶段)

准备:

  1. 为类变量(static变量)分配内存,并赋予对应数据类型的零值
  2. 声明为final类型的类变量则在该阶段就完成赋值,并不是赋予零值
  3. 声明为final类型的类变量且使用random函数赋值,则赋予零值

解析:

  1. 将常量池内的符号引用替换为直接引用
  2. 主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类符号引用

初始化:

  1. 从上至下,根据赋值语句对类变量进行赋值
  2. 对类变量的初始化过程被封装于<clinit>函数中,该函数由jvm自动生成,函数内容为类变量赋值语句及static静态代码块
  3. <clinit>函数的执行顺序为先执行父类,再执行本类
  4. 对于接口不做第三条要求
  5. <clinit>函数的执行jvm需保证仅执行一次,即在函数执行上锁,多个初始化线程仅一个线程执行该函数,其余线程需等待函数执行完毕才能使用该类
  6. 当通过子类调用父类的类变量且父类子类介未初始化时,仅会触发父类的<clinit>函数
  7. 类数组并不会触发累的初始化,如 自定义类A[] 数组不会触发自定义类A的初始化
  8. 调用 final类型的类变量也不会触发初始化
2.类加载时机

只有“主动使用”类时才会触发类的初始化,包括以下情形:

  1. 遇到new、getstatic、putstatic、invokestatic四条字节码指令时,对应类未初始化
  2. 使用Refelct反射调用类,对应类未初始化
  3. 初始化子类时父类未初始化,则父类需要先初始化
  4. 定义main函数的类在虚拟机启动时,被先初始化
  5. 使用JDK 1.7 MethodHandle 动态语言 解析为 getstatic、putstatic、invokestatic时,且方法对应的类未初始化时
3.双亲委派机制

根据JVM规范,类加载器分为引导类加载器及用户自定义类加载器(包括扩展类加载器、应用程序类加载器、自定义加载器)。

双亲的翻译来源可能时根据JVM规范定义来的,只有两种类加载。

双亲委派机制是指:当JVM需要加载一个类时,先向其父类加载器询问是否能够加载或是否加载过此类,询问直至引导类加载器,若父类加载器都无法加载,再由其自己加载,否则直接由父类加载器加载该类或使用父类加载器加载的该类。

引导类加载器(bootstrap classloader) jre/lib/*,如rt.jar

扩展类加载器(extension classloader) jre/lib/ext/*.jar

应用程序类加载器(application classloader) classpath

自定义类加载器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值