一、jvm一个类的加载过程
一个类加载到jvm内存,到jvm内存的卸载,会经历七个阶段,也就是他的生命周期:
加载——验证——准备——解析——初始化——使用——卸载
其中验证、准备、解析阶段统称为链接,于是乎整个过程变成了
加载——链接——初始化——使用——卸载。
加载:主要通过classpath、jar包、网络、某个磁盘位置中类的class二进制字节流读取,在内存中生成一个代表这个类的java.lang.Class对象放入元空间。此阶段可以干预,使用自定义类加载器来实现。
链接:主要是为了验证加载的类是否符号虚拟机的规范,然后给类变量进行初始化赋值,带有static的变量,或者final关键字的常量,不带有static关键字的变量会在对象被创建的时候进行赋值,同样也是默认值。
public static int a; // 链接的时候进行初始化赋值 a = 0
public static final int b = 10; // 链接的时候进行赋值
public int c' // 当对象被使用时初始化赋值,为 c = 0
初始化:当我们使用到这个类或者new对象、反射等使用他的静态属性方法等,就会触发类的初始化,其父类也会被初始化。
卸载:条件苛刻,一般不会实现。
java运行一个类是当需要的时候才进行初始化进行加载的。(按需加载)
二、类被初始化的过程
-
当还没有new对象的时候,首先会加载静态常量、静态变量、静态代码块
当new了对象后,会继续加载普通变量、初始化块、构造器。
继承时父类的初始化顺序是:
父类–静态变量
父类–静态初始化块
子类–静态变量
子类–静态初始化块
父类–变量
父类–初始化块
父类–构造器
子类–变量
子类–初始化块
子类–构造器
记住,属于类本身的都是优先加载,比如带有静态的属性。接着是父类的一切初始化后才轮到子类。
-
类加载器:主要在类“加载”阶段,通过一个类的全限定名来获取描述该类的二进制字节流的这个动作的“代码”被称为“类加载器”(Class Loader),这个动作是可以自定义实现的.
类加载器的级别:应用类加载器——扩展类加载器——启动类加载器
2.1 启动类加载器(bootstrap class loader),使用C语言实现,是虚拟机自身的一部分。并不继承自 java.lang.ClassLoader。
2.2 扩展类加载器(extensions class loader),扩展一些java程序中所需要的东西。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java类——由sun.misc.Launcher$ExtClassLoader实现。
2.3 应用类加载器(application class loader),使用java语言进行编写,它根据 Java 应用的类路径(classpath,java.class.path 路径下的内容)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的——由sun.misc.Launcher$AppClassLoader实现。
三、类加载器的双亲委派机制
关于双亲委派机制在另外一篇博客有提到过:双亲委派机制的理解
补充:沙箱安全机制:对java核心类库的一种保护机制。