类的加载顺序
1.父类静态变量 2.父类静态代码块 3.子类静态变量 4.子类静态代码块 5.父类变量 6.父类非静态代码块 7.父类构造方法 8.子类变量 9.子类非静态代码块 10.子类构造方法
/**
* @Author wangbiao
* @Date 2019-11-23 22:12
* @Decripition TODO
**/
public class ClassLoadTest {
public static void main(String[] args) {
Son son = new Son();
}
}
class Parent{
private static final String first="first";
private static String second = "second";
private String third = "third";
static {
System.out.println("【父类】静态代码块:first:"+first+";second:"+second);
}
{
System.out.println("【父类】非静态代码块:first:"+first+";second:"+second+"third:"+third);
}
public Parent(){
System.out.println("【父类】构造方法:first:"+first+";second:"+second+"third:"+third);
}
}
class Son extends Parent{
private static final String fourth="fourth";
private static String fifth = "fifth";
private String sixth = "sixth";
static {
System.out.println("【子类】静态代码块:fourth:"+fourth+";fifth:"+fifth);
}
{
System.out.println("【子类】非静态代码块:fourth:"+fourth+";fifth:"+fifth+"sixth:"+sixth);
}
public Son(){
System.out.println("【子类】构造方法:fourth:"+fourth+";fifth:"+fifth+"sixth:"+sixth);
}
}
类的加载过程
1.加载:通过类的全限定名称找到要加载的二进制字节流文件加载到内存中,将静态存储结构转变成方法去的运行时数据结构,并在堆内存里面创建一个class对象作为访问方法区类信息的入口
2.验证:验证加载进来的数据是否符合虚拟机的规范,并且不会危害虚拟机的安全。验证包括文件格式验证、元数据验证、字节码验证、符号引用验证、文件格式验证:验证加载进来的数据是否符合class文件的规范,只有符合规范了,数据才能被存储到方法区。
3.准备:给静态变量分配内存空间,这个内存空间是在方法区中的,并且会给默认值,默认值一般是0,如果类有静态变量的话就会直接赋初值。
4.解析:将常量池里面的符号引用转变成直接引用
5.初始化:执行类构造器,类构造器方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。即执行给类变量赋值和执行静态代码块里面的内容,如果这个类继承了父类,那么先执行父类的类变量赋值和静态代码块的内容。所以这里就和前面代码执行的输出过程相验证。先是执行类静态变量赋值,再执行静态代码块,最后执行构造方法。
6.在堆中分配内存空间:分配内存空间包括父类和子类的所有实例变量,但不包括静态变量
7.对实例变量赋值:将方法区里面的实例拷贝一份到堆中,赋默认值,应该赋初值的。
8.执行费静态代码块和构造方法,如果有父类,先执行父类非静态代码块和构造方法,然后在栈区定义引用变量,并将实例在堆内存地址赋值给引用变量
在堆内存开启存储空间 实例化对象 赋值给引用变量
类的加载机制
1.类加载器分类
根类加载器
它用来加载java核心库,是用原生代码来实现的,并不继承自java.lang.ClassLoader
加载扩展类和应用程序类加载器。并指定他们的父类加载器。
扩展类加载器
用来加载java的扩展库。java虚拟机的实现会提供一个扩展库目录。该类加载器再此目录里面查找并加载java类
应用类加载器
它根据java应用的类路径来加载java类,一般来说,java应用的类都是它来完成加载的。
自定义加载器
可以自己写一个类加载器,不过类加载器要继承classLoader
2.双亲委派机制
双亲委派机制是当一个类加载器接收到类加载的请求的时候自己首先不去加载,而是交给父类去加载,父类也不去加载,最后都会交给根加载器加载,如果根加载在发现扫描的范围内没有这个类的时候,就叫给父类加载器,父类也没有加载成功的话,就交给子类加载,如果子类加载不成功,那就会报classNotFoundException