1.类的加载
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的java.lang.Class对象,用来封装类在方法区类的对象
2.类的加载机制
我们都知道Java源文件,通过编译器,能够生产相应的.Class文件,也就是字节码文件,
而字节码文件又通过Java虚拟机中的解释器,编译成特定机器.上的机器码。
即如下:
①Java源文件- ->编译器- ->字节码文件
②字节码文件- ->JVM–>机器码
每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是Java为什么能够跨平台的原因了,当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享。
3.类的加载过程
一个java文件从被加载到被卸载这个生命过程,总共要经历5个阶段,JVM将类加载过程分为:
加载->链接(验证+准备+解析)->初始化(使用前的准备)->使用->卸载
(1)加载
就是查找并加载类的二进制数据。
(2)链接:
验证:确保被加载类的正确性;
准备:为类的静态变量分配内存,并将其初始化为默认值;
解析:把类中的符号引用转换为直接引用;
(3)初始化
为类的静态变量赋予正确的初始值
4.类的加载时机
(1)类的初始化
虚拟机规范则是严格规定了有且只有5种情况必须立即对类进行“初始化"(class文件加载到JVM中):
主动初始化的6种方式:
●创建对象实例: new 对象的时候,会对类的初始化,前提这个类没有被初始化←
●调用类的静态属性或为静态属性赋值
●调用类的静态方法。
●通过 class文件反射创建对象。
●初始化一个类的子类: 使用子类的时候先初始化父类
Java虚拟机启动时被标记为启动类的类:比如main方法所在的类
注: Java 类的加载是动态的,它并不会- -次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。
不会进行初始化的情况:
●在同一个类加载 器下面只能初始化类一- 次,如果已经初始化了就不必要初始化了。。
●在编译的时候 能确定下来的静态变量(编译常量),不会对类进行初始化。比如final修饰的静
态变量。
(2)类的初始化顺序
1)如果这个类还没有被加载和链接,那先进行加载和链接 ;
2)假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口);
3)加入类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句;
总得来说,类的初始化顺序依次是:(静态变量、静态初始化块)–>(实例变量、实例初始化块)–> 构造方法;如果有父类,则顺序是:父类static方法 –> 子类static方法 –> 父类构造方法- -> 子类构造方法
5.类加载器类型
当JVM启动的时候,Java开始使用如下三种类型的类加载器:
启动(Bootstrap)类加载器:启动类加载器是用本地代码实现的类加载器,它负责将JAVA_HOME/lib下面的核心类库或-Xbootclasspath选项指定的jar包等虚拟机识别的类库加载到内存中。由于启动类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用。
扩展(Extension)类加载器:扩展类加载器是由Sun的ExtClassLoader实现的,它负责将JAVA_HOME /lib/ext或者由系统变量-Djava.ext.dir指定位置中的类库加载到内存中。
系统(System)类加载器:系统类加载器是由 Sun 的 AppClassLoader实现的,它负责将用户类路径(java -classpath或-Djava.class.path变量所指的目录,即当前类所在路径及其引用的第三方类库的路径。
6. 双亲委派模型
双亲委派模型的工作过程如下:
1.当前类加载器从自己已经加载的类中查询是否此类已经加载,如果已经加载则返回原来已经加载的类;
2.如果没有找到, 就去委托父类加载器去加载。父类加载器也会采用同样的策略,查看自己已经加载过的类中是否包含这个类,有就返回,没有就委托其父类去加载,直到委托到启动类加载器为止。因为如果父类加载器为空了,就代表使用启动类加载器作为父加载器去加载该类。( 也就是看到的String 类加载器为null) ;
3.如果启动类加载器加载失败,就会使用扩展类加载器来尝试加载,继续失败则会使用
AppClassLoader来加载,继续失败就会抛出-一个异常CassNotFoundException。
使用双亲委派模型的好处是
(1)安全性,避免用户自己的类动态替换Java的一些核心类;
(2)避免类的重复加载