JVM系列(3)--Class三大生命周期之Class加载原理

332 阅读2分钟

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

一个class的生命周期分为四步: loading、linking、initalizing、被GC回收。

其中一个class变成完全状态是需要经过loading、linking、initalizing三步 class的4个生命周期.jpg

Loading

Loading就是把一个class加载到内存的过程。

在java中,是通过一种叫做ClassLoader的类进行对类的加载工作的。 双亲委派流程.jpg

ClassLoader是一个顶级父类,针对这个类,有多种类型的子类。 在这些类型中,有一个顶级的类加载器,叫做Bootstrap ClassLoader,它是由C++实现的,负责加载java中的核心库,也因此它在java中并没有对应的对象类型,所以每当想要获得它的时候,都会得到null值。 Bootstrap ClassLoader不但会加载所有核心类库,还负责将除它之外的所有其他类型的ClassLoader进行加载。 其他类型ClassLoader分为三种:

  1. Extension ClassLoader 负责加载java扩展包里的class文件

  2. App ClassLoader 负责加载用户创建的class文件,一般我们写的指定的classpath下的class就都是由它进行加载的。

  3. Custom ClassLoader ,除了上述几种之外,用户还可以继承ClassLoader接口,来实现自己的一套加载类的逻辑,这种都属于自定义的classloader

可以查看一下例子


public class ClassLoaderTest001 {
public static void main(String[] args) {
 //加载java核心包的classloader
System.out.println(String.class.getClassLoader());
//加载java核心包的classloader
 System.out.println(sun.awt.HKSCS.class.getClassLoader());
//加载扩展包里的classloader
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
//当前这个类的classloader
 System.out.println(ClassLoaderTest001.class.getClassLoader());
//加载扩展包里的classloader的classloader
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader());
//加载当前类的classloader的classloader
System.out.println(ClassLoaderTest001.class.getClassLoader().getClass().getClassLoader());
    }
}

打印结果如下:

null //为空,说明是Bootstrap ClassLoader
null //为空,说明是Bootstrap ClassLoader
sun.misc.Launcher$ExtClassLoader@45ee12a7 //ExtClassLoader
sun.misc.Launcher$AppClassLoader@18b4aac2 //AppClassLoader
null //为空,说明是Bootstrap ClassLoader 验证了除Bootstrap ClassLoader之外的ClassLoader的都是由Bootstrap ClassLoader进行加载的
null //为空,说明是Bootstrap ClassLoader 验证了除Bootstrap ClassLoader之外的ClassLoader的都是由Bootstrap ClassLoader进行加载的

各个 ClassLoad 它们之间的关系并不存在继承关系

那是什么关系把它们连接起来的?

它们是存在引用关系的。

也就是自下向上,自定义类加载器有个parent指向App加载器,App加载器有个parent指向Ext加载器,Ext加载器有个parent指向Bootstrap加载器

package jacquesh.jvm.study.classload;

public class ClassLoaderTest002 {
    public static void main(String[] args) {
//加载当前类的classloader的classloader
System.out.println(ClassLoaderTest002.class.getClassLoader().getClass().getClassLoader());
//加载当前类的classloader的parent 
System.out.println(ClassLoaderTest002.class.getClassLoader().getParent());
        
    }
}