首页 > 代码库 > 1.虚拟机类加载机制

1.虚拟机类加载机制

Java虚拟机的类加载机制

1.Java虚拟机的特点

1.1语言无关性

Java虚拟机并不进进支持java语言,可以支持JRuby,JPython,Scala等

1.2平台无关性

Java天生就是为了摆脱操作系统的束缚而产生的,提出了一个"编译一次,任意运行"的口号

总结:

  • Java系的语言通过自己的编译器把源代码编译为字节码存放在class文件中,虚拟机通过加载字节码实现,虚拟机的语言无关性
  • 字节码的功能远远比java语言强大,因为java不能提供的功能,其他的Java系语言可能可以提供,而字节码必须对所有的Java系语言提供底层的技术支持
  • Java的平台无关性是有条件的,比如JDK1.6打的Jar包在JDK1.8的虚拟机上是不能执行的(向下兼容)

 

2.类加载机制概述

2.1概述

类载虚拟机中的使用分为如下的几个步骤

1.加载 2.验证 3.准备 4.解析 5.初始化 6.使用 7.卸载

备注:

  • 解析不一定初始化之前,可能回在初始化之后,这是为了配合java的后期绑定(动态绑定)
  • java动态绑定—一般的函数、不包括被static和final修饰的函数
  • 1.前期绑定:编译器在程序执行之前就知道,调用哪个函数体
  • 2.后期绑定:编译器不知道参数(接口)调用的是哪个对象的函数

2.2 类的初始化

     类的加载时机是交给虚拟机进行把握的,但是对于类的初始化有严格的要求的,因此我们先介绍类的初始化的时机,如下的几种情况会进行虚拟机的类加载

  • 使用new创建的类的对象,使用类的静态变量和调用类的静态函数
  • 利用反射机制使用类时
  • 初始化一个类的时候,如果发现其父类还没有被初始化,应该进行父类的初始化
  • 虚拟机初始化的时候,优先初始化含有main函数的主类
  • 与java的动态语言特性相关----先不介绍

  除了上边的5种情况,其他的情况都不会引起类的初始化,我们称为被动引用  

  • 1.子类调用父类的静态变量或者静态函数不会引起子类的初始化,只会引起父类的初始化
  • 2.定义了类的对象数组,但是没有进行初始化——————————————Father[ ] arrays=new Father[10];是不会调用Father类的构造函数的
  • 3.使用类中的常量,在编译期间会把类的常量加载到方法区的常量池中,所以不会触发类的初始化

2.2.1 接口的初始化

  接口初始化时发现接口的父接口没有进行初始化时是不会进行初始化的,只有到父接口被使用的时候才会进行初始化

2.3 加载过程-----加载是类加载的一个子过程

非数组类的加载----利用类加载器(类必须和类的加载器有一一对应的关系,可以使用用户自己定义的类加载器,也可以使用系统提供的引导加载器)

  1. 根据类名获取相对应的二进制字节码------不一定从类的Class文件中获取,加载完之后会把类进行初始化的
  2. 将二进制字节码中的类的相关静态变量提取出来,放到虚拟机的方法区的运行时数据结构中
  3. 在内存中生成一个该类的Class对象,提供类的方法去中的运行时数据结构的访问入口------比较特殊不一定在堆中进行创建

数组类的加载

  • 数据是由虚拟机直接产生的,数据存放的类型(数据减一纬)是由类加载器产生的
  • 数组的类型的创建过程如下:
      • 类型是引用类型---递归调用该类型的类加载器创建数组中的元素 
      • 类型不是引用类型-使用引导加载器进行创建,eg:int[]

 

1.虚拟机类加载机制