类加载过程:
1.加载->链接->初始化
2. 链接:验证,准备,解析
3. 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的java.lang.Class对象,用来封装类在方法区类的对象。
4. 类的加载的最终产品是位于堆区中的Class对象
一
1.类的加载阶段:
加载 验证 准备 解析 初始化 使用 卸载
2.加载 验证 准备 初始化 卸载 的顺序固定不变,解析和使用的顺序可能变化
解析会出现在初始化之前或之后
3.四种情况对类立即执行初始化:
1.遇到new,getstatic,putstatic,invokestatic这四种指令时,立即触发初始化
2.遇到java.lang.reflect包的方法对类进行反射的时候,如果类没有被初始化,则立即触发初始化
3.初始化一个类时,如果其父类还没有被初始化,则立即触发初始化其父类
4.虚拟机启动时,需要指定一个执行的主类(main方法的类),会先初始化这个类
二
1.当通过子类调用父类的静态字段时,只会触发父类的初始化,而不会去触发子类的初始化
2.ClassA [] array = new ClassA[10];->触发了LClassA的类的初始化,它是由JVM自动生成的,直接继承Object的类,创建动作由字节码指令newarray触发。
3.常量会在编译阶段存入调用类的常量池。
*.编译器会为接口生成<clinit>()构造器,用于初始化接口中定义的成员变量。一个接口在初始化时,并不要求其父类接口全部完成了初始化,只有在真正使用到父接口的时候才会初始化。
三.
1.加载:完成三件事
(1)通过一个类的全限定名来获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在Java堆中生成一个代表此类的Class对象,作为访问方法区这些数据的入口。这个加载过程主要就是靠类加载器实现的,这个过程可以由用户自定义的加载过程。
过程:类的全限定名->(获取)定义此类的二进制字节流->将这个字节流代表的静态存储结构->(转化为)运行时数据结构—>生成一个Class对象
2.验证
验证阶段的目的是确保Class文件的字节流中包含的信息符合当前虚拟机的要求,确保JVM安全(编译器自己编译的class文件是安全的,但万一有高手自己写一个class文件来恶意攻击jvm)。主要包括四种验证:
(1)文件格式验证:基于字节流验证,验证字节流是否符合Class文件格式的规范,并且能被当前虚拟机处理
(2)元数据验证:基于方法区的存储结构验证,对字节码描述信息进行语义验证
(3)字节码验证:基于方法区的存储结构验证,进行数据流和控制流的验证
(4)符号引用验证:基于方法区的存储结构验证,发生在解析中,是否可以将符号引用成功解析为直接引用
3.准备
仅仅为类变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值即零值((1)不包含用final修饰的static,因为final在编译的时候就会分配了,(2)同时这里也不会为实例变量分配初始化)。类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
4.解析
解析主要就是将常量池中的符号引用替换为直接引用的过程。
5.初始化
初始化阶段依旧是初始化类变量和其他资源,这里将执行用户的static字段和静态语句块的赋值操作。这个过程就是执行类构造器方法的过程。
*:方法是由编译器收集类中所有变量的赋值动作和静态语句块的语句生成的,类构造器<init>方法与实例构造器方法<client>不同,这里面不用显示的调用父类的方法,父类的方法会自动先执行于子类的方法。即父类定义的静态语句块和静态字段都要优先子类的变量赋值操作。
类加载器
JVM 的类加载是通过ClassLoader及其子类来完成的,以下是类的层次关系和加载顺序
尝试加载类
->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->
Bootstrap ClassLoader —— Extension ClassLoader —— App ClassLoader —— Custom ClassLoader
<-<-<- <-<-<- <-<-<- <-<-<- <-<-<- <-<-<- <-<-<- <-<-<- <-<-<- <-<-<-
检查类是否已经加载
Bootstrap ClassLoader:负责加载$JAVA_HOME中 jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
Extension ClassLoader:负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
App ClassLoader:负责加载classpath中指定的jar包及目录中的class
Custom ClassLoader:属于应用程序根据自身需要自定义的ClassLoader,如tomcat,jboss都会根据j2ee规范自行实现。
ClassLoader加载过程中会先检查类是否已被加载,检查过程中只要某个ClassLoader已加载就视为已加载此类,保证此类只被所有ClassLoader加载一次。