季章节 类加载机制

横流:本文主要参照自《深入理解java虚拟机(第二本子)》

每当查本文前,先使询问JVM内存结构,见 首先节
JVM内存结构

1、类加载流程

  • 拿叙类的数额从xxx.class文件加载到JVM内存
  • 本着这些数量开展校验、准备、解析(这三只经过总称为”链接”)
  • 对这些多少开展初始化,最终形成可叫JVM直接用的Class对象

注意:

  • 类加载过程是以运行期完成的

 

2、加载

  • 企图:把叙类的数目从xxx.class文件加载到JVM内存
  • 斯等完成三桩事
    • 经一个看似的全限定类名来获取定义此类的老二上前制字节流
    • 用是字节流所表示的静态存储结构转化为方法区的周转时数据结构
    • 在术区生成一个java.lang.Class对象,作为方法区内该类的各种数据的访问入口
  • 注意:
    • 仿佛加载的好是依全限定类名和类加载器(ClassLoaderA实例)完成,这片单元素呢是标识一个已于加载类的标识
    • 接口、类:名称也”全限定类名+ClassLoader实例ID”,这种类型的类由所在的ClassLoader负责加载
    • 数组:”[核心型”或”[L引用类型;”(eg.byte[] bytes = new
      byte[512];//类名为”[B”;Object[] objs = new
      Object[10];//类名为”[Ljava.lang.Object;”)

      • 在意基本型名称还是获得自首字母大写(eg.byte:B),有半点单例外boolean:Z;long:J
      • 频繁组类由JVM直接创造,其数组元素由类似加载器加载

 

3、验证

  • 季局部验证
    • 文件格式验证:当通过一个近乎的全限定类名获取了定义此类的老二上前制字节流后,检验该字节流是否满足class文件格式(例如:开头是魔数,主次版本号是否是时虚拟机处理范围中,即是否当次到主之间的本,高于主的本不加载(这就是亚版本的jdk无法尽高版本jdk的来由),等等),检验过后,执行”加载”部分的老二码事,将数据放入方法区并蕴藏
      • 格式不合乎:java.lang.VerifyError
    • 长数据证明:保证类的老大数据信息可java语言专业(例如:这个类若是普通类,是否实现了那个落实接口下的所有类)
      • 至于类的首位数据有什么,查看 次回
        Javac编译原理
    • 验证方法体的许节码指令,确定指令顺序符合逻辑
    • 记引用验证:
      • 发生在条分缕析阶段:将标志引用转化为直接引用的经过
      • 本着符引用的辨证,保证这些标记引用(属性、方法齐)存在,并且具有相应的权(eg.保证private的点子不可让另外类似看)
        • NoSuchMethodError、NoSuchFieldError、IllegalAccessError
  • 注意:
    • 证明阶段可能会见越过插在相近加载的另阶段
    • -Xverify:none:关闭大部分底验证操作,这个我们一般不会见部署是参数(即我们一般还是碰头错过做证明的),因为类似加载虽然发运行期,但是多数底接近加载行为是以服务器启动之时刻即便生了,实际上不影响我们的程序运行。当然,如果我们手动调用了Class.forName(),this.getClass.getClassLoader().loadClass(),这样即使会实施及马上句代码的下加载类,但说到底是个别。通常我们见面利用Class.forName()来引入MySQL驱动,这也不怕是以maven中引入MySQL驱动包的当儿,其scope是runtime的案由。

 

4、准备

  • 企图:为接近变量分配内存(这些内设有方法区分配)、设置类变量零值
  • 注意:
    • 呢接近变量分配内存(为static对象分配内存,这吗便是static变量存储在方法区的法则)
    • 类似中之实例变量会就对象实例的创同分配在积中,当然要基本数据列的话,会趁对象的开创直接压入操作数栈
    • 为static变量分配零值(默认零值)(eg.static
      int x = 123;//这时刻x = 0,而x = 123凡在”初始化”阶段来的)
    • 啊final变量分配初始值(期望值)(eg.final
      int y = 456;//这下y = 456)

 

5、解析

  • 意:符号引用转化为直接引用
  • 符引用(编译期):存储于class文件之常量池中(见 老三回
    类文件结构与javap的运),只来部分号,没有实际的地方
  • 直引用(运行期):在拖欠阶段,会也标记引用分配实际的内存,之后符号引用就转会为了直接引用,存储于运作时量池
    • 常量池:class文件被的概念
    • 运作时量池:JVM内存结构中方法区内之一个有
  • 注意
    • 欠手续在”初始化”阶段前不肯定有,但是毫无疑问要在一个符号引用被应用前解析。

 

6、初始化

  • 用意:执行静态片(static{})、初始化(按意愿)static变量(eg.static
    int x = 123;//”准备”阶段后,x = 0;”初始化”后,x = 123)、执行构造器
  • 来的机会:
    • new:执行构造器
    • 子类调用了初始化,若父类没有初始化,则父类先使初始化(eg.子类调用了”new
      无参构造器”,则先使尽父类的”无参构造器”)
    • 映调用了看似,若类没有初始化,需要先初始化
    • 虚拟机启动时,包含main()方法的类要初始化
  • 小心:static{}与static变量初始化的起非自然会发出在服务器启动时(即未必然有在类加载时),若想要高达容器启动后,就实行同样段落代码xxx,可以将类似实现spring的InitalizingBean,重写该接口下之afterPropertiesSet()方法,将xxx代码写副该方式被。

 

总结:

  • 恍如加载流程
    • “加载”第一品级:通过一个好像的全限定类名来获取定义此类的老二上制字节流
    • “验证”第一级:文件格式验证
    • “加载”第二流:将这字节流所表示的静态存储结构转化为方法区的运作时数据结构
    • “加载”第三等级:在点子区生成一个java.lang.Class对象,作为方法区内该类的各种数码的拜会入口
    • “验证”第二流:元数据证明
    • “验证”第三品级:验证方法体的许节码指令
    • “准备”第一阶段:类变量分配内存
    • “准备”第二等MySQL:设置类变量零值
    • “验证”第四号:符号引用验证(追随于”解析”,仅发生在”解析”的早晚)
    • “解析”:符号引用转化为直接引用(不是要使以”初始化”之前的步骤的步骤)
    • “初始化”:不自然生在何时,但是毫无疑问要在”加载”、”验证”、”准备”之后
  • 关于验证部分,我们可能会见猜疑既然javac在”语法分析”和”语义分析”部分已召开了大量的印证,类加载的时段怎么还要进行验证?
    • javac并没有召开在接近加载部分的有所证,例如:魔数验证
    • 非是拥有的class文件还是出于javac产生的,还有第三方的jar,甚至是祥和伪造之class
  • 如上步骤,从”验证”第二阶段开始交”初始化”之前,都是于方法区进行,这个地方为是近乎加载的要紧场合。
网站地图xml地图