读书笔记——深入理解JAVA虚拟机(3)

来源:互联网 发布:手机怎么注册开淘宝店 编辑:程序博客网 时间:2024/06/06 01:09

第七章  虚拟机类加载机制

7.1概述

所谓虚拟机类加载,指的是虚拟机将编译器编译好的Class字节码文件加载到内存,并对数据进行校验和初始化,最终形成一个可以被虚拟机使用的JAVA类。

类的加载、校验和初始化是在运行期完成的(懒加载)。

7.2类加载的时机

类的生命周期:

加载——验证——准备——解析——初始化——使用——卸载

什么样的场景下需要对类进行加载呢?

1、new对象、读取或设置类的静态字段(常量除外)、调用类的静态方法。

2、反射。

3、虚拟机启动时,main()方法所在的类。

4、当加载一个类的时候,总是会先加载它的父类。

几个容易混淆的场景:

1、通过子类引用父类的静态字段,不会初始化子类。因为对于静态字段,在使用的时候只有直接定义它的类才会初始化。

2、通过数组定义来引用类,不会导致该类的初始化。例如:

MyClass[] myClasses = new MyClass[10];
MyClass对象不会初始化。

3、调用某个常量,不会导致该常量所在类的初始化。因为对于常量来说,在编译的时候,就会把常量放到调用类字节码文件的常量池中,本质上并没有直接引用到定义该常量的类。

7.3类加载的过程

1、加载字节码文件:通过1个类的全名称获取其二进制的字节流。注意,这里的加载并不一定是Class文件,还可以是其他形式。

2、校验:虚拟机会对加载进来的数据进行校验,包括格式、语义等等,校验完成后,就会在虚拟机的方法区中开辟出内存空间,将字节码表示的数据结构存放起来。

3、准备:虚拟机正式为类变量分配内存并设置其初始的零值。注意:这里仅仅包括类的静态变量。常量不包括在内,常量在编译时就已经初始化好了。

4、解析:将类常量池中的符号引用转化为直接引用,即将类方法名与方法的实际内存地址、类字段名与字段的实际内存地址关联起来。

5、初始化:执行类中的静态代码块,静态变量的赋值等动作,这些动作是程序员在代码里定义的。顺序与源码中的顺序一致。

7.4类加载器

判断两个类是否相等

1、类的加载器是否相等

2、类是否相等

上面两个条件必须同时满足。

类加载器的类型:

1、启动类加载器(Bootstrap ClassLoader):用来加载JVM依赖的类,即<JAVA_HOME>\lib目录下的类,最顶层的类加载器,一般来说不用管。

2、扩展类加载器(Extension ClassLoader):用来加载<JAVA_HOME>\lib\ext目录下的类,一般也不用管。

3、应用程序类加载器(Application ClassLoader):用来加载Classpath下的类,一般都用这个。

双亲委派模型:当要加载一个类时,底层的类加载器永远会先委托上层的类加载器去加载,只有在上层不加载时,才会自己加载。这样可以保证同一个类永远是由同一个类加载器来加载。






原创粉丝点击