类加载过程(一)

类加载全过程:加载、验证、准备、解析、初始化

一、加载

“加载”是类加载(Class Loading)过程的一个阶段。加载阶段,虚拟机需要完成以下3件事:

  • 通过一个类的全限定名来获取定义此类的二进制字节流
  • 将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

虚拟机规范对这3点的要求并不具体,例如“ 通过一个类的全限定名来获取定义此类的二进制字节流 ”,并没有指明二进制字节流要从一个Class文件中获取,准确的说是根本没有指明要从哪里获取、怎样获取。在此之上,诞生了很多对Java影响重大的技术,如:

  • 从ZIP包中读取,后发成为JAR、WAR、EAR格式的基础
  • 从网络中读取,应用于Applet等
  • 运行时计算生成,应用于动态代理
  • 由其他文件生成,应用于JSP
  • 从数据库读取,应用于某些中间件服务器

相对于类加载过程的其他阶段,非数组类的加载阶段既可以使用系统提供的引导类加载器,也可以使用自定义类加载器完成(重写一个类加载器的loadClass()方法)。

对于数组类而言,数组类本身不同类加载器创建,它是由Java虚拟机直接创建的。但数组类的元素类型(Element Type,指的是数组去掉所有维度的类型)最终是要靠类加载器去创建,一个数组类C创建的过程要遵循以下规则:

  • 如果数组的组件类型(Component Type,指的是数组去掉一个维度的类型)是引用类型,那就递归采用本节中定义的加载过程去加载这个组件类型,数组C将在加载该类组件类型的类加载器的类名称空间上被标识
  • 如果数组的组件类型不是引用类型(如,int[]数组),Java虚拟机将会把数组C标记为与引导类加载器关联
  • 数组类的可见性与它的组件类型的可见性一致,如果组件类型不是引用类型,那数组类的可见性将默认为public

加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式由虚拟机实现自定义。然后在内存中实例化一个java.lang.Class类的对象并没有明确规定是存放在Java堆中,对于HotSpot虚拟机而言,Class对象比较特殊,它虽然是对象,但是存放在方法区里面),这个对象将作为程序访问方法区中的这些类型数据的外部接口。

加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两阶段的开始时间仍然保持着固定的先后顺序。

发表评论

邮箱地址不会被公开。 必填项已用*标注